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

Monks,

I have an academic regex question. I was trying to convert an ip to a hex number, for say, solaris jumpstarts, doing

 echo 123.45.67.890 | perl -ne '/(\d+)\.(\d+)\.(\d+)\.(\d+)/;printf "%X%X%X%X\n",$1,$2,$3,$4

easy enough. Question is, Is there a way to get the values expanded from a quantifer? Say something like..

echo 123.45.67.890 | perl -ne '/((\d+)\.?/{1,3}/;printf "%X%X%X%X\n",$1,$2,$3,$4'

Which obviously does not work.. but shows the type of thing I want to know.. Are there implicit variables there and if so how can you access them?

Replies are listed 'Best First'.
Re: extracting variables from regex
by Juerd (Abbot) on Apr 02, 2002 at 21:54 UTC

    Question is, Is there a way to get the values expanded from a quantifer?

    No. But maybe variable interpolation helps:

    echo 123.45.67.890 | perl -ne'$ip = join ".", ("(\d{1,3})") x 4; /^$ip +$/; printf ...'
    Still, you shouldn't be using a regex for this. Consider using split:
    echo 123.45.67.890 | perl -ne'printf "%X%X%X%X\n", split /[\.\s]/'
    Btw: 123.45.67.890 is not a valid IP address ;) When you have come to your senses and thought of a valid IP, think about using unpack.

    U28geW91IGNhbiBhbGwgcm90MTMgY
    W5kIHBhY2soKS4gQnV0IGRvIHlvdS
    ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
    geW91IHNlZSBpdD8gIC0tIEp1ZXJk
    

Re: extracting variables from regex
by tadman (Prior) on Apr 02, 2002 at 23:57 UTC
    As they say, "Look, Ma! No regex!"
    echo 12.34.56.78 | perl -MSocket -ne "printf('%08X',unpack('N',inet_aton(\$_)))"
    Sometimes people get caught up in a situation not unlike "when all you have is a regex, everything looks like a pattern". Especially with e-mail addresses and URLs.

    As a note, the Socket inet_aton function will also resolve host addresses (i.e. "www.yahoo.com") and will reject malformed IP addresses (i.e. "123.456.789.012").
Re: extracting variables from regex
by dws (Chancellor) on Apr 02, 2002 at 22:16 UTC
      printf "%X%X%X%X\n",$1,$2,$3,$4 Is going to cause you (or someone downstream of you who happens to have a different IP address) no end of grief. I think you'll be happier with   printf "%02X%02X%02X%02X\n",$1,$2,$3,$4
(Ovid) Re: extracting variables from regex
by Ovid (Cardinal) on Apr 02, 2002 at 21:59 UTC

    If I understand your question correctly, wouldn't it make sense to do the following?

    $ echo 123.45.67.890 | perl -ne 'for $x(1..3){/(\d+)/g; printf "%X", $ +1}' 7B2D43

    The $x is there just to prevent $_ from being overwritten.

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

Re: extracting variables from regex
by RMGir (Prior) on Apr 02, 2002 at 21:58 UTC
    I don't think so, apart from the famous (infamous?) $`, $&, and $', the variables which should not be named (or used).

    But if you recast your regex slightly, you can get SOME information.

    With a quantifier, a capturing paren shows the last element matched. But by adding another set of parens AROUND the quantifier, you can get the "grouped match".

    /(\d\.?){1,4}/ # $1 is last octet matched /((\d\.?){1,4})/ # $1 is IP address, $2 is last octet matched
    (Edit:You're better off using the other approaches suggested in the other responses, though)

    Not really useful in this case, I admit, but then again, for your academic case all you really needed was a call to split :)

    echo 1234.45.67.890 | perl -ne'printf "%X%X%X%X",split /\./'
    (Edit:Juerd is right, I should have used the split in list context)
    --
    Mike

      echo 1234.45.67.890 | perl -ne'split /\./; printf "%X%X%X%X",@_'

      From split's documentation:

      In scalar context, returns the number of fields found and splits into the @_ array. Use of split in scalar context is deprecated, however, because it clobbers your subroutine arguments.
      Why not have split in list context, and forget about @_?
      printf "...", split /\./

      U28geW91IGNhbiBhbGwgcm90MTMgY
      W5kIHBhY2soKS4gQnV0IGRvIHlvdS
      ByZWNvZ25pc2UgQmFzZTY0IHdoZW4
      geW91IHNlZSBpdD8gIC0tIEp1ZXJk
      

        Why have split at all?
          
        echo 192.168.0.1 | perl -nle 'printf "%02X"x4, /\d+/g'
           MeowChow                                   
                       s aamecha.s a..a\u$&owag.print
        Because... No particular reason :)

        I always do that for one liners, out of laziness.

        For any real script, I use -w and strict, and have gotten out of the bad habit.

        You're right, I shouldn't be doing it in one-liners, either.
        --
        Mike

Re: extracting variables from regex
by belden (Friar) on Apr 03, 2002 at 02:21 UTC
    My first thought was a bit clunky:

    echo 66.218.71.112 | perl -pe 's/([\d]{1,3}(?:\.|$))/sprintf("%X",$1)/ge'
    42DA4770

    And though I don't think these are the best solutions in the world, they might make you dig into perlrun (I sure had to to come up with these!)

    echo 66.218.71.112 | perl -F'\.' -ane 'printf "%X%X%X%x\n",@F'
    42DA4770

    echo 66.218.71.112 | perl -0056 -ane 'printf "%X",$_'
    42DA4770

    blyman
    setenv EXINIT 'set noai ts=2'

Re: extracting variables from regex
by pizza_milkshake (Monk) on Apr 03, 2002 at 20:03 UTC
    well, you could do something like:
    print hex for split/\./
    perl -MLWP::Simple -e'getprint "http://parseerror.com/p"' |less