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?

3
  • 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. Commented May 31, 2017 at 6: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. Commented May 31, 2017 at 6: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. Commented May 31, 2017 at 6:46

1 Answer 1

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).

1
  • Yep, that seems to be it. Commented Jun 19, 2019 at 15:26

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.