http://qs1969.pair.com?node_id=1192253

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

How to pre-pending a timestamp to each line of output from a command? Something like this https://i.stack.imgur.com/3EIM1.gif

I tried the following code, but fail to achieve it :(

use strict; use warnings; use POSIX q(strftime); my @abc = ("a", "b", "c", "d", "e"); my $time=POSIX::strftime('%a, %d %b %Y %T %z', localtime); foreach (@abc) { print "[$time]\t$_\n"; sleep 5;}
  • Comment on How to Prepending a timestamp to each line of output from a command
  • Download Code

Replies are listed 'Best First'.
Re: How to Prepending a timestamp to each line of output from a command
by choroba (Cardinal) on Jun 07, 2017 at 09:18 UTC
    prepend.pl:
    #!/usr/bin/perl use warnings; use strict; use Time::HiRes qw{ time }; my $start = time; while (<>) { printf '%3.7f | %s', time - $start, $_; }

    Test run:

    for i in {1..10} ; do sleep .2 ; echo $i ; done | prepend.pl

    If you want to overwrite a line, don't output "\n" at its end, but use "\r" instead, it will move the cursor to the beginning of the same line.

    Update: See Time::HiRes , printf, and Quote and Quote like Operators.

    ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
Re: How to Prepending a timestamp to each line of output from a command
by Discipulus (Canon) on Jun 07, 2017 at 09:20 UTC
    hello jnarayan81,

    First of all you are assigning to $time once, so even if the format will work you'll end with the same time at each print: you must call it at each iteration directly or with a sub.

    Second I do not find %a to be valid in the format description, see the following code:

    use strict; use warnings; use POSIX q(strftime); my @abc = ("a", "b", "c", "d", "e"); foreach (@abc) { print '[',(strftime '%Y-%m-%d-%H-%M-%S', localtime()) +. "]\t$_\n"; sleep 1;} #output [2017-06-07-11-19-36] a [2017-06-07-11-19-37] b [2017-06-07-11-19-38] c [2017-06-07-11-19-39] d [2017-06-07-11-19-40] e

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: How to Prepending a timestamp to each line of output from a command
by haukex (Archbishop) on Jun 07, 2017 at 10:36 UTC

    Hmm, gnomon is a neat little tool. Just for the heck of it, here's a really simple Perl version (works on Linux, probably not on Windows):

    #!/usr/bin/env perl use warnings; use strict; use IO::Select; use Time::HiRes qw/ gettimeofday tv_interval /; my $sel = IO::Select->new(\*STDIN); $|=1; my $t0 = [gettimeofday]; while (1) { my $line; if ($sel->can_read(.1)) { defined( $line = <STDIN> ) or last } printf "%7.3f | %s", tv_interval($t0), $line//"\r"; $t0 = [gettimeofday] if defined $line; }

      This code is magic. I am trying to implement in my program but fail due to little understanding.

      #!/usr/bin/env perl use warnings; use strict; use IO::Select; use Time::HiRes qw/ gettimeofday tv_interval /; my @abc = ("a", "b", "c", "d", "e"); for my $v(@abc) { my $sel = IO::Select->new($v); $|=1; my $t0 = [gettimeofday]; while (1) { my $line; if ($sel->can_read(.1)) { defined( $line = $v ) or last } printf "%7.3f | %s", tv_interval($t0), $line//"\r"; $t0 = [gettimeofday] if defined $line; } sleep 1; }

      Is this possible to make it a subroutine and call it by default in all STDOUT?

        I'm sorry, but I don't fully understand what you're trying to do. It would be best if you could explain more, with a runnable SSCCE, example input and expected output. Otherwise I am left guessing, for example, based on your code it's not clear to me what @abc contains. Is this a list of commands you want to run, or is it the output of another command? If it's the latter, note that the other monks have already shown you how to handle that, like Discipulus's post here. How are you running the external command, from the command line with the input piped to the Perl script like in the gnomon example (which my code handles), or do you want to invoke the external command from inside the Perl script? If it's the latter, note that my code might not be the best way to do this, and you might need to switch to a module like IPC::Run.

        Is this possible to make it a subroutine and call it by default in all STDOUT?

        Are you asking how you can modify your own Perl script's output to prefix it with the current time (like a log), instead of another program's output?

Re: How to Prepending a timestamp to each line of output from a command
by thanos1983 (Parson) on Jun 07, 2017 at 12:07 UTC

    Hello jnarayan81,

    The monks have already provided you with wisdom, but I am wondering why don't you simply call it through a subroutine. Your script works just fine as soon as you call the subroutine every instance that you want it.

    Sample:

    #!usr/bin/perl use say; use strict; use warnings; use POSIX q(strftime); my @abc = ("a", "b", "c", "d", "e"); sub fetchTime { return POSIX::strftime('%a, %d %b %Y %T %z', localtime); } for (@abc) {say fetchTime() . "\t$_"; sleep 1;} __END__ $ perl time.pl Wed, 07 Jun 2017 14:08:31 +0200 a Wed, 07 Jun 2017 14:08:32 +0200 b Wed, 07 Jun 2017 14:08:33 +0200 c Wed, 07 Jun 2017 14:08:34 +0200 d Wed, 07 Jun 2017 14:08:35 +0200 e

    Hope this helps.

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: How to Prepending a timestamp to each line of output from a command
by dbander (Scribe) on Jun 07, 2017 at 11:37 UTC