1

I'm reading the famous awk tutorial from http://www.grymoire.com/Unix/Awk.html.

In which it mentioned To be precise, in the original AWK you can insert a new line character after the curly braces, and at the end of a command, but not elsewhere.

I got the following multiple line awk command test on my mac and remote host, with awk and gawk:

  awk '$0 !~ /special_signal/  \
       { my_dict[$1] += $2 }
       END { for (uid in my_dict)   \
             if (my_dict[uid] > 1)  \
             print uid, my_dict[uid]}' raw_data | sort -nk2

The original one-line awk command of the above awk code is:

awk '$0 !~ /special_signal/ { my_dict[$1] += $2 } END { for (uid in my_dict) if (my_dict[uid] > 1) print uid, my_dict[uid]}' raw_data | sort -nk2

Through my experiments. I found on both awk and gawk, the first \ is essential, without it, the code will behave differently compare to the original one-liner. The effect of new-line character is identical to ;

But the second and third \ after for (uid in my_dict) and if (my_dict[uid] > 1) in all these two awk edition are unnecessary.

I removed them, the multiple code act as exactly the same as one-liner.

Then I replaced the second and third \ with ;, which will leads the multiple-line code produce a wrong result.

This further proved that If I add a new-line character after after for (uid in my_dict) and if (my_dict[uid] > 1), they'll just connect these two code blocks with the code of next-line, act like a \.

My conclusion seems conflict with the tutorial.

So, indeed, at which circumstances will awk treat new-line as ; and at which as treat it as \?


PS: for the sake of test, I've made some test content for raw_data:

Tom 2
Tom 5
Jack 3
Mary 5
special_signal 5
Tim 10
Don 22
Jan 3
Jack 8
special_signal 10

1 Answer 1

3

The difference between your example lines is: Can the command be finished at that point? A pattern can stand alone; in that case {print} is assumed. The next line is considered a second command (not the second part of the first one); the pattern is assumed to be always true.

But within a control structure (for, if) you cannot finish the command at that point thus it is clear that the command is continued on the next line.

It is similar in shell code:

echo foo &&
echo bar

is interpreted differently than

echo foo
&& echo bar

so you need

echo foo \
&& echo bar

With the difference to awk that only one way works. But there may be similar cases.

6
  • This can it be finished? comes from the view of human being. But for awk, { for (uid in my_dict) if (my_dict[uid] > 1) print uid, my_dict[uid]} and { for (uid in my_dict); if (my_dict[uid] > 1); print uid, my_dict[uid]} are all executable command and act differently. So, by what logic the awk designer judged the can it be finished?, do you know the mechanism of that?
    – Zen
    Feb 8, 2015 at 13:53
  • @Zen No, the "can it be finished?" refers to the awk perspective i.e. the awk syntax, of course. Feb 8, 2015 at 13:56
  • I'm confused. Because I test it, and a single for (uid in my_dict) can run. Though nothing print out, it simply iterate over the my_dict, and do nothing. And a single if (my_dict[uid] > 1) simply checks if there is a my_uid, if uid in my_dict, and if my_dict[uid] > 1, then do nothing.
    – Zen
    Feb 8, 2015 at 14:01
  • I mean, did the author write something like: if we got a bare for block or if block we treat new-line as ``. How could I figure it out by reading like source code or something as a newbee who has no C-language knowledge.
    – Zen
    Feb 8, 2015 at 14:04
  • For practice consideration I can accept this answer, until I met another exception next time. But I really want to know if there is an official doc or something.
    – Zen
    Feb 8, 2015 at 14:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .