Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

using Backtick inside perl gives different output

by kaka_2 (Sexton)
on Oct 07, 2013 at 16:32 UTC ( [id://1057280]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Monks,

I have written a script to get the offset valu on a solaris machine. and below is code:

#!/usr/bin/perl use strict; use warnings; my $cmd = "/usr/sbin/ntpq -p"; my @ntpout = grep (/^\*/, `$cmd`); # grep line starting with * sign a +nd put into an array my $file = 'offset.txt'; open (my $fh, '>' $file) or die "Could not open file '$file' $!"; print $fh "@ntpout\n"> close $fh; # Written array output into file my $offset = `cat offset.txt | awk '{print $9}'`; # here expecting 9th + cloumn value in variable $offset print "$offset \n";

raw output of $cmd is:

remote refid st t when poll reach delay offset + disp ====================================================================== +======== LOCAL(0) LOCAL(0) 10 l 34 64 377 0.00 0.000 + 10.01 *gpstime.domain.l .PPS. 1 u 879 1024 377 1.85 -0.02 +5 0.03 hitman.domain.lo 0.0.0.0 16 - - 1024 0 0.00 0.00 +0 16000.0

when i run command "cat offset.txt | awk '{print $9}'"outside of script it gives me exactly "-0.025" but when i debug the script and added a watch for $offset i see it returns "*gpstime.domain.l .PPS. 1 u 879 1024 377 1.85 -0.025 0.03"

What wrong i am doing? -KAKA-

Replies are listed 'Best First'.
Re: using Backtick inside perl gives different output
by toolic (Bishop) on Oct 07, 2013 at 16:56 UTC
    qx interpolates variables. try to escape $9:
    my $offset = `cat offset.txt | awk '{print \$9}'`;
      Thank you for pointing out to use \ before $.
Re: using Backtick inside perl gives different output
by johngg (Canon) on Oct 07, 2013 at 18:01 UTC

    As Laurent_R points out, this can be much more simply done in Perl. Taking your raw output as my input, I grep any lines of interest then pass them through a map. Split breaks each line up and I pull out the 9th element (subscript 8 as subscripts are zero-based) from the map and print it.

    $ perl -Mstrict -Mwarnings -E ' open my $ntpqFH, q{<}, \ <<EOD or die $!; remote refid st t when poll reach delay offset + disp ====================================================================== +======== LOCAL(0) LOCAL(0) 10 l 34 64 377 0.00 0.000 + 10.01 *gpstime.domain.l .PPS. 1 u 879 1024 377 1.85 -0.02 +5 0.03 hitman.domain.lo 0.0.0.0 16 - - 1024 0 0.00 0.00 +0 16000.0 EOD my @asteriskLines = grep m{^\*}, <$ntpqFH>; say for map { ( split )[ 8 ] } @asteriskLines;' -0.025 $

    I hope this is of interest.

    Cheers,

    JohnGG

Re: using Backtick inside perl gives different output
by Laurent_R (Canon) on Oct 07, 2013 at 16:59 UTC

    Why don't you simply read your values from the @ntpout variable, rather than this complicated way of writing to a file and then use awk in a system command? It would be so much simpler and would avoid polluting your disk with useless files.

Re: using Backtick inside perl gives different output
by ig (Vicar) on Oct 07, 2013 at 18:25 UTC

    As suggested by Laurent R, you might consider using more Perl and less files and system commands.

    If you like terse, you might try something like:

    use strict; use warnings; my $cmd = "/usr/sbin/ntpq -p"; my $offset = (split(/\s+/, (grep(/^\*/, `$cmd`))[0]))[8]; print "$offset\n";

    If you find that a bit difficult to read and would prefer several statements with intermediate variables, you might try something like:

    use strict; use warnings; my $cmd = "/usr/sbin/ntpq -p"; my @ntpout = `$cmd`; my $current_time_source = (grep(/^\*/, @ntpout))[0]; my $offset = (split(/\s+/, $current_time_source))[8]; print "$offset\n";

    You should also think about what will happen if there are errors or unexpected situations. You might change the latter to something like:

    use strict; use warnings; my $cmd = "/usr/sbin/ntpq -p"; my @ntpout = `$cmd`; die "$cmd failed with: $^E, $?" unless(@ntpout); my $current_time_source = (grep(/^\*/, @ntpout))[0]; die "Not synchronized" unless($current_time_source); my $offset = (split(/\s+/, $current_time_source))[8]; die "$current_time_source: No offset" unless(defined($offset)); print "$offset\n";
      This is what i wanted to do but i was spliting @ntpout without getting value for my $current_time_source and i still dont understand why would you do so?
Re: using Backtick inside perl gives different output
by AnomalousMonk (Archbishop) on Oct 07, 2013 at 23:01 UTC

    With warnings enabled, Perl will complain if you try to interpolate an uninitialized or undefined variable, and if there has never been a regex capture to capture group 9, that's what the special variable  $9 will be. See Variables related to regular expressions in perlvar for discussion of  $1 $2 $3 $n   etc.

    So one wrong you have done is to ignore the warnings you asked Perl to give you.

    >perl -wMstrict -le "my $sw = '/b'; my $d = `dir $sw $9`; print qq{'$d'}; " Use of uninitialized value $9 in concatenation (.) or string at -e lin +e 1. 'arb_nested_HoH_1.pl arb_struct_access_1.pl arb_struct_access_2.pl ... most_of_8_1.pl recurring_cycle.pl recurring_cycle.pl.bak '
Re: using Backtick inside perl gives different output
by jwkrahn (Abbot) on Oct 07, 2013 at 23:33 UTC

    Another way to do it:

    #!/usr/bin/perl use strict; use warnings; open my $cmd, '-|', '/usr/sbin/ntpq', '-p' or die "Cannot open pipe fr +om ntpq because: $!"; while ( <$cmd> ) { my $offset = ( split )[ 8 ]; print "$offset\n" if /^\*/; } close $cmd or warn $! ? "Error closing ntpq pipe: $!" : "Exit status $? from ntpq";

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1057280]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (8)
As of 2024-04-18 06:41 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found