nidhi has asked for the wisdom of the Perl Monks concerning the following question:

Monks!
Here are few of the lines of a config file i need to scan :
interface Vlan1 no ip address no ip route-cache shutdown ! interface Vlan12 ip address 68.142.192.79 255.255.255.0 no ip route-cache shutdown ! interface Vlan8 ip address 68.142.192.79 255.255.255.0 no ip route-cache !
I need to create a hash of keys for eg : Vlan8,Vlan12 (not Vlan1) and value containing : 8,12 respectively. Only those key-value pair gets stored which has an ip address given in the next 1 or more lines. I tried the following :
while(<IN>) { my ($key) = /^(interface Vlan[\d]*)/; next if $key =~ /^\s ip address \d*\.\d*\.\d*\.\d* \d*\.\d*\.\d*\.\d*/ +; # next if $key =~ /^\s*$/; my ($value) = /^interface Vlan([\d]*)/; $hash1{$key} = $value ; }

but keep getting the following result :
interface Vlan1 => 1 interface Vlan8 => 8 interface Vlan12 => 12
I dont' want Vlan1. plz. help!

Replies are listed 'Best First'.
Re: create key-value pair
by GrandFather (Saint) on Aug 28, 2007 at 21:30 UTC

    One way to do it is to change what constitutes a "line end". In this case ! looks like a good character to choose as a line end character. Consider:

    use warnings; use strict; $/ = '!'; while (<DATA>) { next unless /ip address (?:\d+\.){3}\d+/; next unless /interface (\w+(\d+))/; print "$1 -> $2\n"; } __DATA__ interface Vlan1 no ip address no ip route-cache shutdown ! interface Vlan12 ip address 68.142.192.79 255.255.255.0 no ip route-cache shutdown ! interface Vlan8 ip address 68.142.192.79 255.255.255.0 no ip route-cache !

    Prints:

    Vlan12 -> 2 Vlan8 -> 8

    DWIM is Perl's answer to Gödel
Re: create key-value pair
by bruceb3 (Pilgrim) on Aug 28, 2007 at 21:39 UTC
    Hi!
    #!/usr/bin/perl # vim: sw=4 use strict; use warnings; my ($vlan, $ipaddress, $netmask); my %interfaces; # great variable name. while (<DATA>) { if (/^interface Vlan(\d+)/) { $vlan = $1; } elsif (/no ip address/) { ($vlan, $ipaddress, $netmask) = (undef, undef, undef); next; } elsif (/ip address ((\d+\.){3}\d+) ((\d+\.){3}\d)/) { ($ipaddress, $netmask) = ($1, $3); } elsif (/^!$/ && $ipaddress && $netmask) { $interfaces{$vlan}->{ip} = $ipaddress; $interfaces{$vlan}->{netmask} = $netmask; } } use Data::Dumper; print Dumper \%interfaces; __DATA__ interface Vlan1 no ip address no ip route-cache shutdown ! interface Vlan12 ip address 68.142.192.79 255.255.255.0 no ip route-cache shutdown ! interface Vlan8 ip address 68.142.192.79 255.255.255.0 no ip route-cache !
    The output of this code is-
    $VAR1 = { '8' => { 'ip' => '68.142.192.79', 'netmask' => '255.255.255.0' }, '12' => { 'ip' => '68.142.192.79', 'netmask' => '255.255.255.0' } };
Re: create key-value pair
by runrig (Abbot) on Aug 28, 2007 at 21:41 UTC
    Another possibility (more error checking is left as an excercise):
    my $key; while (<IN>) { chomp; if ( my $status = /^interface Vlan/.../^!/ ) { $key = $_ if $status == 1; if ( /^\s*ip address (?:[\d.]+)/ ) { my ($value) = $key =~ /(\d+)/; $hash{$key} = $value; } } }
    or
    my $key; while (<IN>) { if ( /^(interface Vlan(\d+))/ ) { $key = $1; $hash{$1} = $2; } delete $hash{$key} if /no ip address/; }
Re: create key-value pair
by Fletch (Bishop) on Aug 28, 2007 at 21:29 UTC

    Erm, next if /no ip address/;?

    Update: Wait, I just looked more closely. You're looking at $key for something it can't possibly contain. Something's really screwy with your logic.

    Update 2: The way I'd do this (if the data's not amenable to monkeying with the record separator as has been suggested) would be to write a little parser. The state you'd want to keep would be the last interface line you'd seen, and you'd use that as the key when you see any ip address #.#.#.# lines. If you don't see any of those before the next interface line nothing's stored.

    Update 3: . . . which runrig has just given an example of below . . .

Re: create key-value pair
by McDarren (Abbot) on Aug 28, 2007 at 21:41 UTC
    my %interfaces; while (<DATA>) { if (/interface Vlan(\d+)/) { next if $1 == 1; $interfaces{"Vlan$1"} = $1; } } print Dumper(\%interfaces);
    ...gives the result that you say that you want. Although I have a sneaky suspicion that this is not all that you want ;)
Re: create key-value pair
by brent.allsop (Acolyte) on Aug 29, 2007 at 03:01 UTC
    Is this what you want?
    my ($key, $value); while(<IN>) { if ($_ =~ m/^(interface Vlan([\d]*))/) { $key = $1; $value = $2; } if ($_ =~ m/^ ip address \d*\.\d*\.\d*\.\d* \d*\.\d*\.\d*\.\d*/) { $hash1{$key} = $value ; } }