Why does '-1' not work in Awk but '(-1)' does?

94 Views Asked by At

I was doing some data filtering and noticed something a bit strange.

As we all know, awk '1' is short for awk '{print $0}', since 1 evaluates to True and triggers that default action on Awk, which consists on printing the current record.

Similarly, awk '0' does not print anything because it evaluates to False.

$ seq 3 | awk '0'
                      # nothing
$ seq 3 | awk '1'
1
2                     # everything
3

So I tried different approaches on this and noticed that awk '-1' gives an error, while awk '(-1)' works without a problem:

$ seq 3 | awk '-1'
Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:      GNU long options: (standard)
...
        # all the gawk explanation on how to use it
...
$ seq 3 | awk '(-1)'
1
2                     # everything, since apparently
3                     # -1 evaluates to True

The same with awk '-NF' or awk '-NR' or any other expression starting with the negative character.

Why is this?

I am on GNU Awk 4.1.65, API: 2.0.

1

There are 1 best solutions below

1
Sundeep On BEST ANSWER
seq 3 | awk '-1'

is same as

seq 3 | awk -1

single/double quotes can be used to construct an argument on command line depending on what's needed, for ex:

$ echo 'foo baz' | grep 'foo b'
foo baz
$ echo 'foo baz' | grep foo\ b
foo baz

$ echo 'foo:baz:123' | awk '-F:' '{print $1}'
foo
$ f='-F:'; echo 'foo:baz:123' | awk "$f" '{print $1}'
foo
$ var='$1'; echo 'foo:baz:123' | awk '-F:' "{print $var}"
foo

Coming back to awk -1, the -1 gets treated as an option (because options start with - or -- depending on tool). -1 is not a valid option, so we get an error

Most tools have a workaround for such cases, using -- will indicate no further option

$ seq 3 | awk -- -1
1
2
3

More examples:

$ # echo is fine with echoing non-options starting with -
$ echo '-1'
-1
$ echo '-1' | grep '-1'
Usage: grep [OPTION]... PATTERN [FILE]...
Try 'grep --help' for more information.
$ echo '-1' | grep -- '-1'
-1

$ echo 'Foo' | grep 'foo'
$ # using option at end depends on tool, I think it is GNU specific
$ echo 'Foo' | grep 'foo' -i
Foo
$ echo 'Foo' | grep -- 'foo' -i
grep: -i: No such file or directory

Further reading: Difference between terms: "option", "argument", and "parameter"?