23

I have the following file party.txt that contains something like the following:

Hello Jacky
Hello Peter
Bye Johnson
Hello Willy
Bye Johnny
Hello Mary
Hello Wendy

I used the grep hello to capture the contents, but when I use the print date +"%Y-%m-%d' and append to it, I cannot, and I will get many 0 per line.

cat party.txt | grep Hello | awk '{ print date +"%Y-%m-%d"}'

What could I be missing?

Kevin
  • 16,549
  • 8
  • 60
  • 74
Jack
  • 1,603
  • 5
  • 25
  • 36

8 Answers8

42

gawk (and recent versions of mawk) have a built-in time/date function, so there is no need to use external tools there.

gawk '/Hello/{print NR " - " $0 " - " strftime("%Y-%m-%d")}' party.txt
mwfearnley
  • 3,303
  • 2
  • 34
  • 35
Alin
  • 421
  • 4
  • 2
  • the only change I would make is to replace awk with gawk on operating systems where awk is not the POSIX/GNU compliant version. Well, that and to remove the line number which wasn't part of the original request. – Armand Aug 22 '14 at 18:10
34

One way using awk:

awk -v date="$(date +"%Y-%m-%d %r")" '/Hello/ { print $0, date}' party.txt

Results:

Hello Jacky 2012-09-11 07:55:51 PM
Hello Peter 2012-09-11 07:55:51 PM
Hello Willy 2012-09-11 07:55:51 PM
Hello Mary 2012-09-11 07:55:51 PM
Hello Wendy 2012-09-11 07:55:51 PM

Note that the date value is only set when awk starts, so it will not change, even if the command takes a long time to run.

mwfearnley
  • 3,303
  • 2
  • 34
  • 35
Steve
  • 51,466
  • 13
  • 89
  • 103
  • If combine with danfuzz's answer, it would be near to perfect. – Jack Sep 12 '12 at 04:14
  • 4
    The problem I have with this solution, is that the date is set once. if you have a file (or stream) that takes several seconds or minutes to parse, every entry will have the exact same date/time stamp. Also awk is not the universal command that supports -v, nawk is. on Solaris, this won't work, but if you replace awk with nawk, it will work, you could also use gawk (the POSIX/GNU compliant version). I prefer Alin's answer which works on all awk implementations and operating systems (provided awk is replaced by gawk) – Armand Aug 22 '14 at 18:09
4
 awk 'BEGIN{"date +'%Y-%m-%d'"|getline d;}/Hello/{print $0,d}' file

will give you:

Hello Jacky  2012-09-11
Hello Peter 2012-09-11
Hello Willy 2012-09-11
Hello Mary 2012-09-11
Hello Wendy 2012-09-11
Kent
  • 189,393
  • 32
  • 233
  • 301
4

This solution should work with any awk:

awk '/Hello/ {cmd="(date +'%H:%M:%S')"; cmd | getline d; print d,$0; close(cmd)}' party.txt

The magic happens in close(cmd) statement. It forces awk to execute cmd each time, so, date would be actual one each time.

cmd | get line d reads output from cmd and saves it to d.

fedorqui
  • 275,237
  • 103
  • 548
  • 598
Jimilian
  • 3,859
  • 30
  • 33
3

To answer the direct question, what you're missing is that date is an external command, and so you need to either invoke it outside of awk and pass it in as a variable (as one of the other answers demonstrates), or invoke it from within awk as a system command either using the system() built-in or a pipe (as another one of the other answers demonstrates).

The reason you see 0 is because the expression date +"%Y-%m-%d" is being interpreted as adding the numeric value of the variable date (which will be 0 as it's not defined) to the numeric value of the string "%Y-%m-%d" (which will be 0 as it's not a valid number).

danfuzz
  • 4,253
  • 24
  • 34
0

If you're open to using Perl:

perl -MPOSIX -lne 'if (/Hello/){ print "$_ " . strftime "%Y-%m-%d",localtime }' party.txt

produces this output

Hello Jacky 2015-10-01
Hello Peter 2015-10-01
Hello Willy 2015-10-01
Hello Mary 2015-10-01
Hello Wendy 2015-10-01

Here's how it works:

  • -n loops around every line of the input file, do not automatically print each line

  • -l removes newlines before processing, and adds them back in afterwards

  • -e execute the perl code

  • $_ is the current line

  • -MPOSIX loads the POSIX module, which includes strftime

  • localtime and strftime prints the time, given the format %Y-%m-%d

Chris Koknat
  • 3,305
  • 2
  • 29
  • 30
0

using posix sed (and a sub shell due to missing time function in sed)

sed -n "/^Hello/ s/$/ $( date +'%Y-%m-%d' )/p" party.txt

return

Hello Jacky 2016-11-10
Hello Peter 2016-11-10
Hello Willy 2016-11-10
Hello Mary 2016-11-10
Hello Wendy 2016-11-10
NeronLeVelu
  • 9,908
  • 1
  • 23
  • 43
0

In gawk only:

$ gawk '/Hello/ {print $0, strftime("%Y-%m-%d");}' party.txt 
Hello Jacky 2019-09-17 
Hello Peter 2019-09-17 
Hello Willy 2019-09-17 
Hello Mary 2019-09-17 
Hello Wendy 2019-09-17 
dr-who
  • 189
  • 6