On Wed, Nov 17, 2010 at 3:26 AM, Rob Dixon <[email protected]> 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
>
your drop in script works, I guess plain old logic wins this time :)
did minor modification to the regex since I also have _ or maybe other
characters in the file.
if ($level == 0 and /^(.*?)\s\{$/)
--
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
http://learn.perl.org/