1

the following script will only run the BEGIN and END blocks:

#!/bin/awk -f

BEGIN {print "Hello, World!"}
{ print "Don't Panic" }
END { print "and we're panicking... I told you not to panic.  Did you miss that part?" }

and the output is:

$ awk -f joint.awk .
  Hello, World!
  and we're panicking... I told you not to panic.  Did you miss that part?

the expected output is:

$ awk -f joint.awk .
  Hello, World!
  Don't panic
  and we're panicking... I told you not to panic.  Did you miss that part?

what's odd is that when I change the middle block to print $1, instead of printing a piece of text, it runs as expected when I pass a file in.

oguz ismail
  • 1
  • 16
  • 47
  • 69
Zach Folwick
  • 893
  • 10
  • 18
  • Is there any data on stdin? The middle block is only run when there's data. – Charles Duffy Oct 10 '21 at 02:54
  • See for example https://ideone.com/tggrLw -- two lines of input, and you get `Don't Panic` printed twice. Zero lines of input, and it never gets printed at all. – Charles Duffy Oct 10 '21 at 02:55
  • 1
    `awk -f joint.awk .` would produce an error message (or warning in GNU awk) about `.` being a directory instead of a file. It's important to read any warning or error messages you get from running tools and to include any such messages when you post questions. In a file that you pass to awk using `-f` any shebang present is ignored as just a comment. If you want to write a shell command that calls awk then a) don't name it with a ".awk" extension, and b) don't call awk with the shebang within it, use a shell in the shebang and call awk from it, see https://stackoverflow.com/a/61002754/1745001. – Ed Morton Oct 11 '21 at 02:51

1 Answers1

4

The inner line with explicit no condition gets run once per line of input on stdin (or in your input file, if one is explicitly named).

Thus, how many times Don't Panic gets printed depends on how much input there is.

See this tested by the following code:

awkScript=$(cat <<'EOF'
BEGIN {print "Hello, World!"}
{ print "Don't Panic" }
END { print "and we're panicking... I told you not to panic.  Did you miss that part?" }
EOF
)
 
echo "Testing with no input:"
awk "$awkScript" </dev/null
echo
echo "Testing with one line of input:"
awk "$awkScript" <<<"One line of input"
echo
echo "Testing with two lines of input:"
awk "$awkScript" <<<$'First line\nSecond line'

...which emits as output:

Testing with no input:
Hello, World!
and we're panicking... I told you not to panic.  Did you miss that part?

Testing with one line of input:
Hello, World!
Don't Panic
and we're panicking... I told you not to panic.  Did you miss that part?

Testing with two lines of input:
Hello, World!
Don't Panic
Don't Panic
and we're panicking... I told you not to panic.  Did you miss that part?
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441