3

While having a go at Convert date in bash shell, I tried GNU awk's coprocess feature:

gawk -F, -v cmd='date +"%Y-%m-%d %H:%M:%S" -f-' '{print $5 |& cmd; cmd |& getline d; $5 = d}1' foo

This command hangs. I thought this might be because date is waiting to read the entire input, so I tried to close the sending half of the pipeline:

gawk -F, -v cmd='date +"%Y-%m-%d %H:%M:%S" -f-' '{print $5 |& cmd; close(cmd, "to"); cmd |& getline d; $5 = d}1' foo

This works (yes, I know I should set OFS=,, but for now...).

However, date seems to have no problem processing input as it comes in. This gives the first line of output immediately:

d='Thu Apr 27 2017 23:19:47 GMT+0700 (ICT)'
(echo "$d"; sleep 1m; echo "$d") |
  date +"%Y-%m-%d %H:%M:%S" -f-

What's going on?

muru
  • 72,889
  • You're writing, then reading from the same process. This is a well-known deadlock case, nothing to do with date or gawk in particular. It's pretty hard to solve, too. – Satō Katsura May 31 '17 at 06:37
  • @SatoKatsura sure, but date, unlike say, sort, shouldn't have to process input line-by-line... If this is really that common, the coprocess feature would be worthless. – muru May 31 '17 at 06:38
  • Processing input line by line helps if you have unbuffered (or at least line-buffered) I/O. Perl has IPC::Open2 to work around this problem. No idea what gawk does about it. – Satō Katsura May 31 '17 at 06:46

1 Answers1

1

Like many other programs, date's output is buffered when stdout is not a tty. Invoking it through stdbuf -oL you'll have it flush output at each line, and your first Gawk sample code will just work (no need to close the pipe's write end).

LL3
  • 5,418