awk freezing when I direct to a file

2019-08-12 01:13发布

问题:

So when I run this on a mac:

awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' >> app-deployment.yaml

awk just freezes. If I change it to just print to /dev/null like this

awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' < /dev/null

It works fine. Am I doing something wrong with my redirection? Is there something else I'm doing wrong here?

回答1:

Change END to BEGIN to be able to work without any input:

awk 'BEGIN { for (name in ENVIRON) {
  print "key: "name; }
}' >> app-deployment.yaml


回答2:

If an awk program consists of only actions with the pattern BEGIN, and the BEGIN action contains no getline function, awk shall exit without reading its input when the last statement in the last BEGIN action is executed. If an awk program consists of only actions with the pattern END or only actions with the patterns BEGIN and END, the input shall be read before the statements in the END actions are executed.

source: POSIX awk Standard

So in short:

  • awk 'BEGIN{ action-without-getline }': awk exits without processing any input files
  • awk 'BEGIN{ action-with-getline }': awk exits after processing the input files
  • awk 'END{ action }': awk exits after processing the input files
  • awk 'BEGIN{action}END{ action }': awk exits after processing the input files
  • awk 'BEGIN{action; exit}END{ action }': awk exits without processing any input files

But what if there are no input files specified:

Execution of the awk program shall start by first executing the actions associated with all BEGIN patterns in the order they occur in the program. Then each file operand (or standard input if no files were specified) shall be processed in turn ...

source: POSIX awk Standard

So this just means that

$ awk 'END{action}'

will not hang, but awaits input from /dev/stdin



回答3:

OP's Code1 analysis:

awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' >> app-deployment.yaml

Doesn't have any Input_file passed to awk and END block in any awk code requires any Input_file to be passed,it hangs there since it is NOT able to find one.



OP's Code2 analysis:

awk 'END { for (name in ENVIRON) {
  print "key: "name; }
}' < /dev/null

Now you are passing /dev/null as an Input to awk(though it will NOT have any contents to be read by awk but still it has a Input passed to it), so as per rule once Input_file is done processing END block processes, in this case since NO contents are there so END section printing of statements should happen.

To make awk code work without passing an Input_file way: In case anyone wants to awk to work without Input_file use only BEGIN section, which as per man awk page will be executed before Input_file gets processed so even you are NOT passing any Input_file it will NOT wait for its presence and once BEGIN section is executed it will come out of program.