3
votes

I'm having trouble to understand the difference of behavior of awk when using field separators passed through the command line and using FS=":" in a script.

I thought using -F to supply the field separator and using the FS variable in awk were the same thing.

But if I do:

awk -F: '{}' /etc/passwd

it prints nothing as expected because of the empty action ({}). And also, if I put on a script:

#!/usr/bin/awk -f
{}

no lines are printed to the output, as expected.

Now, if I put the field separator in the script, as in:

#!/usr/bin/awk -f

FS=":";
{}

it prints all lines again!

So, I want to suppress the default print action in a script, because I am going to do some computation in the action and print the result later in an END section. How can I do that without awk printing all the lines first?

2

2 Answers

11
votes
FS=":";

This line doesn't do what you think it does. It isn't an instruction. Awk doesn't work like most interpreted languages: a file is not a list of instructions. At the top level, you have items of the form CONDITION ACTION, where the condition is an expression an the action is a brace-delimited block containing statements (instructions). The action is executed for each record (line) that satisfies the condition. Both the condition and the action are optional.

An assignment is an expression, so FS=":" is an expression, and there is no corresponding action. When the action is omitted, it defaults to “print the current record”. As for {} on the next line, it's an action that does nothing, with no condition (which means “always”); writing nothing has the same effect.

To execute code when the script starts, you need a BEGIN block. You can think of BEGIN as a special condition which matches once at the beginning of the script before any input is read.

BEGIN {FS = ":"}
2
votes
> /foo/  { }  # match foo, do nothing - empty action
> 
> /foo/       # match foo, print the record - omitted action

here