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

Oh Great Ones,

I'm trying to extract the network handle from a whois query. Here is the results of doing a whois query with the ip of 216.68.40.234:
[whois.arin.net] Fuse Internet Access (NETBLK-FUSE-NET-BLK-1) FUSE-NET-BLK-1 216.68.0.0 - 216.68 +.255.255 Fuse Modem Ports (NETBLK-FUSE-216-68-32-0) FUSE-216-68-32-0 216.68.32.0 - 216.6 +8.47.255 To single out one record, look it up with "!xxx", where xxx is the handle, shown in parenthesis following the name, which comes first.
The little piece of code below obtains the network handle (anything within the parentheses) which works, but it only matches the first handle. What is the best way to match the second handle also? I thought maybe the /g modifier would work, but it doesn't (well, at least the way I have it). I plan on using this in a larger script to perform a whois query by the second handle.

Thanks,
Dru
#!/usr/bin/perl -w use strict; my $arin="/usr/bin/whois -h whois.arin.net"; my $ip = "216.68.40.234"; my $result = `$arin $ip`; if ($result =~ m/xxx/){ $result =~ m/\((.*?)\)/g; print "The handle is: $1\n"; print "The 2nd handle is: $2\n"; }

Replies are listed 'Best First'.
Re: Regex Help
by japhy (Canon) on Sep 07, 2001 at 02:07 UTC
    A global regex in scalar (or void) context only matches once. Also, there is only a $DIGIT variable made for each set of capturing parentheses in your regex. What you want to use is:
    @handles = $result =~ /\((.*?)\)/g; print "Handles are: @handles\n";

    _____________________________________________________
    Jeff[japhy]Pinyan: Perl, regex, and perl hacker.
    s++=END;++y(;-P)}y js++=;shajsj<++y(p-q)}?print:??;

      ah. I never knew you could assign an array like that. Works like a champ now. Thanks -Dru

Re: Regex Help
by demerphq (Chancellor) on Sep 07, 2001 at 02:09 UTC
    Hi, Ok two problems. The first is that your pattern makes me uneasy. The usual way to sort this type of problem is figure out what you dont want to match. So instead of saying
    m/\((.*?)\)/g;
    I would prefer to see
    m/\(([^)]*)\)/gm;
    I suppose in pure terms both work acceptably, but the class one seems more understandable as 'up to a )' to me.
    use strict; use warnings; my $s=<<EOF; [whois.arin.net] Fuse Internet Access (NETBLK-FUSE-NET-BLK-1) FUSE-NET-BLK-1 216.68.0.0 - 216.68.255.255 Fuse Modem Ports (NETBLK-FUSE-216-68-32-0) FUSE-216-68-32-0 216.68.32.0 - 216.68.47.255 EOF if (my @parts = ($s=~/\(([^)]*)\)/gm)) { print "\n@parts\n"; }
    And secondly, using the match in list contents gives you all of the matches you need.

    Update: Fixed my incorrect observation about the m modifier for the regex as correctly pointed out by dvergin in comment on Re: Regex Help. My apologies

    HTH

    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

      Regarding: "M for 'multiline' matching, ie dont stop at the new line".

      Ummm... no. The '/m' modifier only effects the matching of '^' and '$' (when used to match beginning-of-line, end-of-line). It allows these two symbols to match newlines within the string.

      The regex m/\(([^)]*)\)/g, will match across new lines. More specifically, the regex m/[^)]/ will match a newline quite happily. if ( "\n" =~ /[^)]/ ) {print "Yes\n"} Yes

        Very true.
        I apologise. For some reason I got confused. For me the mantra is 'Ignore, multi-line, as single,' and I forgot the ^$ part.
        And yes I did want to match a newline with my class. What if one were embedded in the () (forget the origin of the text for a second)
        Ill fix my post.

        Yves
        --
        You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)

Re: Regex Help
by Cine (Friar) on Sep 07, 2001 at 01:54 UTC
    A good choice is always cpan whois...

    T I M T O W T D I