Question

This is the configuration I have, and I'm trying to consolidate this into a single route command that i could paste into a Cisco ASA.

set device "internal"
set dst 13.13.13.13 255.255.255.255
set gateway 172.16.1.1

set device "internal"
set dst 14.14.14.14 255.255.255.255
set gateway 172.16.1.1

set device "internal"
set dst 15.15.15.15 255.255.255.255
set gateway 172.16.1.1

Join it to a single device, then modify it accordingly to end up looking something like this

route internal 13.13.13.13 255.255.255.255 172.161.1.1

then the other 3 lines can go away.

I'd like to do this in Perl since i'm writing other scripts to do other portions of the source configuration

Was it helpful?

Solution

Assuming that your order is always device,dst,gateway then this works:

use strict;
use warnings;


my @devices=(); #Array to store device strings
my $current_device=""; #String to capture current device.

while(<DATA>)
{
    chomp;
    if(/^set (\w+) (.+)$/)
    {
        if($1 eq "device")
        {
            $current_device="route $2";
            $current_device=~s/"//g;
        }
        elsif($1 eq "dst")
        {
            $current_device.=" $2";
        }
        elsif($1 eq "gateway")
        {
            $current_device.=" $2";
            push @devices,$current_device;
        }
    }
}

print "$_\n" foreach(@devices);




__DATA__
set device "internal"
set dst 13.13.13.13 255.255.255.255
set gateway 172.16.1.1

set device "internal"
set dst 14.14.14.14 255.255.255.255
set gateway 172.16.1.1

set device "internal"
set dst 15.15.15.15 255.255.255.255
set gateway 172.16.1.1

The output is:

route internal 13.13.13.13 255.255.255.255 172.16.1.1
route internal 14.14.14.14 255.255.255.255 172.16.1.1
route internal 15.15.15.15 255.255.255.255 172.16.1.1

OTHER TIPS

If your configuration file consists of "paragraphs" (stanzas) separated by blank lines as your input suggests, you might do:

#!/usr/bin/env perl
use strict;
use warnings;
local $/ = ""; #...paragraph mode...
while (<>) {
    chomp;
    m{^set.+"internal".+dst\s*([\d\.\s]+$).+gateway\s*(.+)$}ms and
        print "route internal $1 $2\n";
}

Quick hack. This will read in a set of values (separated by two consecutive newlines), put it in a hash, then push that hash onto an array. Using input record separator $/ to read records. Setting $/ to "" the empty string is somewhat like setting it to "\n\n", read more in the documentation linked above.

Not quite sure what you need here. If its just one line merged, simply store the hash without pushing it to an array. It will "remember" the first record.

use strict;
use warnings;

$/ = "";   # paragraph mode
my @sets;
while (<DATA>) {
    my %set;
    chomp;               # this actually removes "\n\n" -- the value of $/
    for (split /\n/) {   # split each record into lines
        my ($set,$what,$value) = split ' ', $_, 3;  # max 3 fields
        $set{$what} //= $value;        # //= means do not overwrite
    }
    $set{device} =~ s/^"|"$//g;        # remove quotes
    push @sets, \%set;
}

for my $set (@sets) {  # each $set is a hash ref
    my $string = join " ", "route", 
        @{$set}{"device","dst","gateway"};  # using hash slice
    print "$string\n";
}

__DATA__
set device "internal"
set dst 13.13.13.13 255.255.255.255
set gateway 172.16.1.1

set device "internal"
set dst 14.14.14.14 255.255.255.255
set gateway 172.16.1.1

set device "internal"
set dst 15.15.15.15 255.255.255.255
set gateway 172.16.1.1

Output:

route internal 13.13.13.13 255.255.255.255 172.16.1.1
route internal 14.14.14.14 255.255.255.255 172.16.1.1
route internal 15.15.15.15 255.255.255.255 172.16.1.1
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top