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/