Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Formatting an array

by bartrad (Sexton)
on Feb 08, 2018 at 00:09 UTC ( #1208668=perlquestion: print w/replies, xml ) Need Help??
bartrad has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I've got an output that I need help formatting as I only want to keep certain bits of it.

/data/alcatel_ethernet_7750/routername1- static-route 1.1.1 +.1/30 next-hop 2.2.2.2 bfd-enable tag 624 /data/alcatel_ethernet_7750/routername2- static-route 1.1.1 +.3/30 next-hop 3.3.3.3 bfd-enable tag 624 /data/alcatel_ethernet_7750/routername3- static-route 1.1.1 +.2/30 next-hop 4.4.4.4 bfd-enable tag 628

I only want to keep the <routername> and <static-route x.x.x.x/30> - I have it stored in an array and opened in a foreach... I'm just struggling with the regex to match what I need

foreach my $line (@grep) { my @arr = $line =~ //g;

Thanks in advance

Replies are listed 'Best First'.
Re: Formatting an array
by roboticus (Chancellor) on Feb 08, 2018 at 02:58 UTC

    bartrad:

    If the fields are always the same length, then substr and unpack can be good choices. Alternatively, if there are consistent delimiters, then split could be a good choice.

    As an example:

    $ cat t.pl use strict; use warnings; for my $line (<DATA>) { # Unpack can pull out multiple fields from a string and also trim +and/or # perform some simple conversions. # You do, however, have to count out your field sizes. my @u_flds = unpack "A52A24A*", $line; print "UNPACK: router: <$u_flds[0]>\n"; print "\ttype and IP: <$u_flds[1]>\n"; # substr can be useful, but you it's a little cumbersome for many +fields. # For only a couple, though, it's not too bad. my $router = substr($line, 0, 52); my $route_and_IP = substr($line,52,24); print "SUBSTR: router: <$router>\n"; print "\ttype and IP: <$route_and_IP>\n"; # Split is good if you have consistent delimiters. If your delimi +ter occurs # in one or more of your fields, though, you may have to glue some + together. my @s_flds = split /\s+/, $line; print "SPLIT: router: <$s_flds[0]>\n"; print "\ttype and IP: <$s_flds[1] $s_flds[2]>\n"; print "\n"; } __DATA__ /data/alcatel_ethernet_7750/routername1- static-route 1.1.1 +.1/30 next-hop 2.2.2.2 bfd-enable tag 624 /data/alcatel_ethernet_7750/routername2- static-route 1.1.1 +.3/30 next-hop 3.3.3.3 bfd-enable tag 624 /data/alcatel_ethernet_7750/routername3- static-route 1.1.1 +.2/30 next-hop 4.4.4.4 bfd-enable tag 628 $ perl t.pl UNPACK: router: </data/alcatel_ethernet_7750/routername1-> type and IP: <static-route 1.1.1.1/30> SUBSTR: router: </data/alcatel_ethernet_7750/routername1- > type and IP: <static-route 1.1.1.1/30 > SPLIT: router: </data/alcatel_ethernet_7750/routername1-> type and IP: <static-route 1.1.1.1/30> UNPACK: router: </data/alcatel_ethernet_7750/routername2-> type and IP: <static-route 1.1.1.3/30> SUBSTR: router: </data/alcatel_ethernet_7750/routername2- > type and IP: <static-route 1.1.1.3/30 > SPLIT: router: </data/alcatel_ethernet_7750/routername2-> type and IP: <static-route 1.1.1.3/30> UNPACK: router: </data/alcatel_ethernet_7750/routername3-> type and IP: <static-route 1.1.1.2/30> SUBSTR: router: </data/alcatel_ethernet_7750/routername3- > type and IP: <static-route 1.1.1.2/30 > SPLIT: router: </data/alcatel_ethernet_7750/routername3-> type and IP: <static-route 1.1.1.2/30>

    While the sample data you provided looks pretty regular, I expect that your field sizes are going to be variable (especially as one is an IP), so I expect that split may be a good choice for you.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      Thanks for the reply, I like this. How would I get rid of the leading path to routernamex as I don't need it?

        bartrad:

        Assuming that all your path components are separated by "/", then you would simply use split again, and take the final component(s):

        my @router_path_components = split qr{/}, $s_flds[0]; my $last_chunk = $router_path_components[-1];

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

Re: Formatting an array
by AnomalousMonk (Chancellor) on Feb 08, 2018 at 02:00 UTC

    Maybe something like:

    c:\@Work\Perl\monks>perl -wMstrict -le "use Regexp::Common qw(net); ;; my @strings = ( '/data/alcatel_7750/routername1- static-route 1.1.1.1/30 next- +hop 2.2.2.2 tag 624', '/data/alcatel_7750/routername2- static-route 1.1.1.3/30 next- +hop 3.3.3.3 tag 624', '/data/alcatel_7750/routername3- static-route 1.1.1.2/30 next- +hop 4.4.4.4 tag 628', ); ;; my $rx_ipv4_dotted_dec = qr{ (?<! \d) $RE{net}{IPv4} (?! \d) }xms; my $rx_routename = qr{ \b [[:alpha:]] \w* \b }xms; my $rx_route = qr{ \b [[:alpha:]] [[:alpha:]-]* \b }xms; ;; for my $s (@strings) { my $parsed = my ($r_name, $r_ip) = $s =~ m{ / ($rx_routename) - \s+ ($rx_route \s+ $rx_ipv4_dotted_dec / \d+) }xms; ;; die qq{bad record: '$s'} unless $parsed; ;; print qq{'$s' -> \n ($r_name) ($r_ip)}; } " '/data/alcatel_7750/routername1- static-route 1.1.1.1/30 next-hop + 2.2.2.2 tag 624' -> (routername1) (static-route 1.1.1.1/30) '/data/alcatel_7750/routername2- static-route 1.1.1.3/30 next-hop + 3.3.3.3 tag 624' -> (routername2) (static-route 1.1.1.3/30) '/data/alcatel_7750/routername3- static-route 1.1.1.2/30 next-hop + 4.4.4.4 tag 628' -> (routername3) (static-route 1.1.1.2/30)


    Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1208668]
Approved by GrandFather
Front-paged by haukex
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others cooling their heels in the Monastery: (6)
As of 2018-06-23 08:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Should cpanminus be part of the standard Perl release?



    Results (125 votes). Check out past polls.

    Notices?