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

Could someone explain what's going on here?

my @trace = split("\s",(`traceroute -w 2 -q 1 -i dmfe0 $ip_address`)); my @trace_out = ""; foreach (@trace){ $_ =~ s/\n//; if ( $_ =~ /some|checks|here/ ){ @trace_out = (split /\s+/, $_ ); } }

and

open EXE, qq{/usr/sbin/traceroute -q 1 -w 2 -i dmfe0 $ip_address |}; my @trace = <EXE>; my @trace_out = ""; foreach (@trace){ $_ =~ s/\n//; if ( $_ =~ /some|checks|here/ ){ @trace_out = (split /\s+/, $_ ); } }
Both work, however, when I use the first I have one server that apparently has hidden characters that would cause the the line to split prematurely. I expect the problem is in the split() in the foreach, but since the open EXE works just fine I'm going with that anyway. Just curious.

Replies are listed 'Best First'.
Re: output difference between backtic and open().
by kcott (Archbishop) on Feb 25, 2014 at 19:19 UTC

    G'day AltGrendel,

    "Both work, however, when I use the first I have one server that apparently has hidden characters that would cause the the line to split prematurely. I expect the problem is in the split() in the foreach, ..."

    I don't think it's the foreach loops. I think it's occurring with "my @trace = ...". Here's my untested guess at what's happening.

    In the first case, you're splitting on a single space 's' character ("my @trace = split("\s", ..."). [Update: see explanation below by ++AnomalousMonk.]

    In the second case, with "my @trace = <EXE>;", you're effectively splitting on a newline ("\n") which is the default value for the input record separator, $/ (see perlvar: Variables related to filehandles).

    Try changing that first line to: my @trace = split("\n", ...

    -- Ken

      In the first case, you're splitting on a single space ("my @trace = split("\s", ...").

      Actually, it's split-ing on the letter 's' because the  \ (backslash) is an escape in a double-quoted string. The escape is unrecognized but passed through, a fact that Perl would have mentioned had warnings been enabled.

      c:\@Work\Perl\monks>perl -wMstrict -le "my $str = 'the rain in spain falls mainly'; ;; my @ra = split \"\s\", $str; printf qq{'$_' } for @ra; print ''; ;; @ra = split '\s', $str; printf qq{'$_' } for @ra; " Unrecognized escape \s passed through at -e line 1. 'the rain in ' 'pain fall' ' mainly' 'the' 'rain' 'in' 'spain' 'falls' 'mainly'

        ++ Well spotted. I've updated my post.

        -- Ken

Re: output difference between backtic and open().
by karlgoethebier (Abbot) on Feb 25, 2014 at 20:06 UTC

    See also Net::Traceroute. Regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

Re: output difference between backtic and open().
by Anonymous Monk on Feb 26, 2014 at 05:11 UTC

    List context will return lines of output:

    my @trace = `traceroute -w 2 -q 1 -i dmfe0 $ip_address`;
Re: output difference between backtic and open().
by dave_the_m (Monsignor) on Feb 26, 2014 at 00:45 UTC
    Split (usually) takes a pattern as its first arg, not a string. So that should probably be
    split(/\s/,(...

    Dave.

      Split (usually) takes a pattern as its first arg, not a string.

      ... but it's perfectly happy with a string; see second example here.