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

I have been trying to streamline some code and have run into a little problem. I can't figure out how to combine or simplify the following: (sample data: $record = " 100.100.100.100    1COMPUTER1       09/13/30828 22:48:05";)
$ipadrs = substr($record,0,17)) =~ s/ //g; @iparray = split(/\./,$ipadrs);
I tried this:
@iparray = split(/\./,(substr($record,0,17) =~ s/ //g));
And this
@iparray = @{split(/\./,(substr($record,0,17) =~ s/ //g))};
Not to mention a few others that were really silly. None of which worked. I've just been guessing at this and I'm not getting any closer to an answer. Perhaps there is no merit in this considering it's only two simple lines of code, but it would be nice to see how this can be done. I would greatly appreciate it if someone could lead me in the right direction.

Replies are listed 'Best First'.
Re: Simplify This
by BrowserUk (Patriarch) on Sep 30, 2003 at 18:46 UTC
    @iparray = ( $record =~ m[(\d+)]g )[0..3];

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
    If I understand your problem, I can solve it! Of course, the same can be said for you.

      This returns a value of 4. I was looking for a value of "100.100.100.100".

      OOPS: Sorry about that. It does return what I was looking for. THANKS

      That's great!! This is short,easy to understand, and doesn't use unnecessary functions. Thanks again.

        Pardon?

        perl> print $record 100.100.100.100 1COMPUTER1 09/13/30828 22:48:05 perl> print +($record =~ m[(\d+)]g)[0..3] 100 100 100 100 perl>

        The original code place the numeric value of the four octets into the array @iparray -- so does this.


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
        If I understand your problem, I can solve it! Of course, the same can be said for you.

        I was looking for a value of "100.100.100.100"

        Huh? From the code you gave, I assumed you were looking for a value of (100, 100, 100, 100) (i.e., a list of four values).


        $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
Re: Simplify This
by jonadab (Parson) on Sep 30, 2003 at 18:54 UTC
    @iparray = $record =~ /^\s*(\d+)[ .]+(\d+)[ .]+(\d+)[ .](\d+)/;
    alternately,
    @iparray = map {s/ //g;$_} split /[.]/, substr ($record,0,17);

    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/
      Both examples return a value of 4. I was looking for "100.100.100.100".

      OOPS: Sorry about that. It does return what I was looking for. THANKS
Re: Simplify This
by tcf22 (Priest) on Sep 30, 2003 at 18:56 UTC
    Try this:
    use strict; use Data::Dumper; my $record = " 100.100.100.100 1COMPUTER1 09/13/30828 22:48:0 +5"; my @iparray = split(/\./, ($record =~ /^\s+([\d\.]+?)\s/)[0]); print Dumper \@iparray; __OUTPUT__ $VAR1 = [ '100', '100', '100', '100' ];

    - Tom

Re: Simplify This
by ChrisR (Hermit) on Sep 30, 2003 at 19:14 UTC
    Of the two solutions presented by jonadab, which is the preferred way?
    @iparray = $record =~ /^\s*(\d+)[ .]+(\d+)[ .]+(\d+)[ .](\d+)/;
    alternately,
    @iparray = map {s/ //g;$_} split /[.]/, substr ($record,0,17);
      The first is better because it's stricter. You definitely want to get the strictest parsing you can, for safety.

      ------
      We are the carpenters and bricklayers of the Information Age.

      The idea is a little like C++ templates, except not quite so brain-meltingly complicated. -- TheDamian, Exegesis 6

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

      I agree with dragonchild. I wouldn't use substr like that:

      my $record = " 127.0.0.1 1COMPUTER1 09/13/30828 22:48:05"; my @iparray = map {s/ //g;$_} split /[.]/, substr ($record,0,17); print "@iparray";

      Output:

      127 00 11COM

      dave

Re: Simplify This
by welchavw (Pilgrim) on Sep 30, 2003 at 20:15 UTC

    I stuck with your overall approach using split and substr. I realize that the regex approaches already given are more elegant, but I am post-happy today. That s// operator returns the number of substitutions, which is what was foiling you. Comma can help, if you like.

    $record = " 100.100.100.100 1COMPUTER1 09/13/30828 22:48:05"; @iparray = split(/\./, do{($copy = substr($record,0,17)) =~ s/ //, $co +py}); $" = "."; print "@iparray";

    ,welchavw

      I agree that the regex's are the better choice here. I actually found the first one by BrowserUk to the best choice.
      @iparray = ( $record =~ m[(\d+)]g )[0..3];
      This is short and easy to understand.
      My mistake in returning the value was in the statement I was using for debugging.
      print "|" . join ".", @iparray . "|\n";
      My guess is that it was returning the number of elements joined. I fixed it as:
      print "|" . (join ".", @iparray) . "|\n";
      Thanks trying to help with a possible reason/answer to my mistake. After tending to the scrapes and bruises from this post, I am back on track and a little wiser for it.

      Thanks to all for your input!