3

The awk manual indicates that both -v FS and -F are equivalent ways to set the field separator.

The GNU Awk User’s Guide -> 4.5.4 Setting FS from the Command Line:

FS can be set on the command line. You use the `-F' argument to do so.

(...)

The value used for the argument to `-F' is processed in exactly the same way as assignments to the built-in variable FS.

However, I noticed that there is a difference if we set it to an empty string, it is not the same. Tested on my GNU Awk 4.1.1.

This works:

$ awk -F, '{print $2}' <<< "a,b,c"
b
$ awk -v FS=, '{print $2}' <<< "a,b,c"
b

But this does not:

$ awk -F="" '{print $2}' <<< "abc"
                                      # $1 contains abc
$ awk -v FS="" '{print $2}' <<< "abc"
b

Why? Is this because setting FS to empty is a gawk specific?

fedorqui
  • 275,237
  • 103
  • 548
  • 598

2 Answers2

5

Looks like you can do this:

$ awk -F '' '{print $2}' <<< "abc"
b

Tested on GNU awk (versions 3.0.4 and 4.1.1) and mawk version 1.2

To be clear, the space between -F and '' is important!

Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
  • Cool, this makes it! Then I noticed `awk -F=","` doesn't work either, so it is probably because `-F` needs the parameter to be given either "glued" or after a space (POSIX way?) – fedorqui Jun 30 '15 at 10:16
  • 1
    @fedorqui Short options (generally) don't use `=` so `-F=","` is the same as `-F=,` which is the same as `FS="=,"`. The space between `-F` and `''` is important because `-F''` just becomes `-F` and then it still needs an argument. – Etan Reisner Jun 30 '15 at 14:54
  • @EtanReisner nice! Is this a POSIX standard or applies to any kind of cases? – fedorqui Jun 30 '15 at 14:55
  • 2
    The POSIX spec for utilities is [here](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html). Guideline 3 says options are single characters. Guideline 6 says options and arguments should be separated by a space. It doesn't cover long options at all that I can see. The behavior above is general getopt operation as far I'm aware but I can't confidently state more than that. If rici or mklement0 see this they'll probably be able to give more concrete answers. – Etan Reisner Jun 30 '15 at 14:59
  • 1
    The reason why this happens is the way Bash processes the command line, not Awk. Bash eats an empty string when it is pressed against a variable, I spoke to the Bash maintainers about this a few months ago. This affects all command line utilities including `read`. E.g. `while read -d '' a b` is not the same as `while read -d'' a b`. –  Apr 08 '16 at 20:35
5

Why? Is this because setting FS to empty is a gawk specific?

Note that the standards say that the results are unspecified if an empty string is assigned to FS. Some versions of awk will produce the output you showed above in your example. The version of awk on OS/X issues the warning and output.

awk: field separator FS is empty

So the special meaning of setting FS to an empty string, does not work in every awk.

Akshay Hegde
  • 16,536
  • 2
  • 22
  • 36
  • 1
    Nice! In fact I think it is `gawk` specific. – fedorqui Jun 30 '15 at 11:35
  • 2
    @fedorqui correct. idk what mawk would do with it, but nawk will report a warning (like the above) and use the default FS while /usr/xpg4/bin/awk will treat it like the whole record is a single field. – Ed Morton Jun 30 '15 at 15:53