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

From a linux prompt I can issue a date command and pipe it to an awk in result getting a single number.

/bin/date | awk 'BEGIN {FS=" "}{print $3}'
In result I get a value of "18", today's day of the month.

I want to capture that single value in my script but it seems when I add a pipe to my command it doesn't work. Here is a snippet of the code:

$day = `/bin/date | awk 'BEGIN {FS=" "}{print $3}'`; print $day;
When this code is run I get "Fri Jun 18 11:48:34 EDT 2010".

How do I get the single value of 18? The above examples are hypothetical, I know there are lots of date modules/packages out there available, I am concern about using pipes in my system calls. Thanks. T

Replies are listed 'Best First'.
Re: system call (backticks) with pipes
by Corion (Patriarch) on Jun 18, 2010 at 16:50 UTC

    See perlop - backticks interpolate, so you would need to be far more careful about including awk programs in your Perl strings.

    Or, alternatively, just throw out date and awk in favour of POSIX:

    my $day = strftime '%d', localtime;
Re: system call (backticks) with pipes
by ikegami (Patriarch) on Jun 18, 2010 at 17:22 UTC
Re: system call (backticks) with pipes
by ikegami (Patriarch) on Jun 18, 2010 at 17:24 UTC

    I am concern about using pipes in my system calls.

    There's nothing special about pipes. There's something special about $, as they interpolate in backticks.

    Since $3 is probably empty,

    my $day = `/bin/date | awk 'BEGIN {FS=" "}{print $3}'`;
    is the same as
    my $day = `/bin/date | awk 'BEGIN {FS=" "}{print }'`;

    Fix:

    my $cmd = q{/bin/date | awk 'BEGIN {FS=" "}{print $3}'}; my $day = `$cmd`;
      Thank you for addressing my actual concern, you seemed to get my dilemma. It worked. Thank you.

      What about a mixed case? I want variable substitution in part of the command.

      $boot_device = q awk 'FNR == 2 { print $1 }'; $boot_device = `$boot_device`; print "$boot_device\n"; $UUID_boot = q awk '{ print $2 }' | sed 's/"//g'; $UUID_boot = `$UUID_boot`; $print "$UUID_boot\n";

      I want $boot_device to be variable expanded but I don't want $2 to be expanded. Using q, the command is being sent as

      blkid $boot_device | awk '{ print $2 }' | sed 's/"//g'

      Using qq the command is being sent as

      blkid /dev/md126p1 | awk '{ print }' | sed 's/"//g'

      which results in an error.

        Then you want to selectively quote the variables using backslashes or construct your strings more carefully by joining them together from other parts:

        print "My two cents: \0.02\n"; my $cat = 'cat'; print "Some awk command: $cat | awk '{ print \$2 }'\n";

        But maybe you just want to use Perl instead of sed and awk? There are even converters that give you the rough Perl code you need for an awk program. See a2p.

        Judging by the unformatted, unreadable and as yet unreaped version of this post,
            $boot_device = q awk 'FNR == 2 { print $1 }';
        and similar are probably intended to be something like
            $boot_device = q[ awk 'FNR == 2 { print $1 }'];
        (and $print should be print).


        Give a man a fish:  <%-{-{-{-<

        I want variable substitution in part of the command.

        So just escape those dollars which you want to pass as literals.

        #!/usr/bin/env perl use strict; use warnings; use Test::More tests => 1; my $boot_device = '/dev/md126p1'; my $cmd = qq#blkid $boot_device | awk '{ print \$2 }' | sed 's/"//g'#; my $shouldbe = q#blkid /dev/md126p1 | awk '{ print $2 }' | sed 's/"//g +'#; is ($cmd, $shouldbe);

        And never pipe awk to sed - that would be pointless.

Re: system call (backticks) with pipes
by Anonymous Monk on Jun 18, 2010 at 16:53 UTC
    #!/usr/bin/perl -- use strict; use warnings; use Time::Piece; my $t = localtime; die $t->mday; # also available as $t->day_of_month __END__ 18 at - line 9.
Re: system call (backticks) with pipes
by Anonymous Monk on Jun 18, 2010 at 17:31 UTC
    I don't have an account yet, but for what it's worth, why not use the date command's output format syntax? Example to get day of the month output from date: /bin/date '+%d'