On Wed, Nov 17, 2010 at 3:26 AM, Rob Dixon <rob.di...@gmx.com> wrote:
> On 16/11/2010 17:01, Vincent Li wrote:
>>
>> Hi List,
>>
>> I have a text test.txt file looks like below:
>>
>> stp instance 0 {
>>    interfaces 1.1 {
>>          external path cost 20000
>>          internal path cost 20000
>>       }
>>    vlans {
>>       internal
>>       vlan10
>>    }
>> }
>> profile http http_global {
>>    defaults from http
>>    max header size 38912
>>    encrypt cookies {
>>       "F-P-SES"
>>    }
>> }
>> profile tcp tcp {
>>    reset on timeout enable
>>    time wait recycle enable
>>    delayed acks enable
>>    proxy mss disable
>> }
>> vlan vlan10 {
>>    tag 1330
>>    interfaces tagged 1.1
>> }
>> route domain 10 {
>>    parent id 0
>>    description "RD10"
>>    vlans vlan10
>> }
>> route domain 12 {
>>    parent id 10
>>    description "RD12"
>>    vlans vlan12
>> }
>>
>> how can I find a specific profile { } block and remove/replace that
>> part from the file, for example, I want to remove below block or
>> replace it with emtpy blank line
>>
>> profile tcp tcp {
>>    reset on timeout enable
>>    time wait recycle enable
>>    delayed acks enable
>>    proxy mss disable
>> }
>>
>> and the { } could have nested { } block too.
>>
>> I tried:
>>
>> perl -e '$/=undef;foreach $profile (<>=~m/profile.*?{.*?}/gs) { print
>> "$profile\n"; }'<  /tmp/test.txt
>>
>> to search and print out the all profile, any tips/sample codes would
>> be very much apprecaited.
>
> Hi Vincent
>
> It is correct that arbitrarily nested blocks cannot be parsed with a single
> regular expression, but there is also no need for anything elaborate.
>
> The program below simply keeps track of the level of nesting by adding the
> number of opening braces and subtracting the number of closing braces on
> each line of the data file. When the level reaches zero a complete block has
> been read and its label determines whether or not it should be output.
>
> HTH,
>
> Rob
>
>
> use strict;
> use warnings;
>
> my %exclude;
> while(<DATA>) {
>  chomp;
>  next unless /(\w[\w\s-]*\w)/;
>  $exclude{$1}++;
> }
>
> open my $profile, '<', 'profile.txt' or die $!;
>
> my $label = '';
> my $block = '';
> my $level = 0;
>
> while (<$profile>) {
>
>  if ($level == 0 and /(\w[\w\s-]*\w)/) {
>    $label = $1;
>  }
>
>  $block .= $_;
>
>  $level += tr/{//;
>  $level -= tr/}//;
>
>  if ($level == 0) {
>    if (not $exclude{$label}) {
>      print $block;
>    }
>    $block = $label = '';
>  }
> }
>
> __DATA__
> profile auth ssl_ocsp
> profile stats stats
> profile stream stream
> profile auth tacacs
> profile tcp tcp
> profile tcp tcp-cell-optimized
> profile tcp tcp-lan-optimized
> profile tcp tcp-wan-optimized
> profile udp udp
>

Thanks everyone replied, I found two similar links on stackflow:

http://stackoverflow.com/questions/133601/can-regular-expressions-be-used-to-match-nested-patterns
http://stackoverflow.com/questions/2700613/how-can-i-extract-a-string-between-matching-braces-in-perl

so looks like there are three options:

1, single magic regex
2, use Text::Balanced
3, plain Perl script to trace {}
4, parser

I tried 1 so far for various regex from the stackoverflow link above,
no success so far. will try 2, then 3.

Thanks.

Vincent

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to