1

I want to write an awk script file using the #!/bin/awk -f header, but I want this script to always use : as a field separator. But for some reason writing #!/bin.awk -F: -f gives me a syntax error. I also want this script to always run on the same file, so I'd like to hardcode that as well. Basically, what I want to work is this:

#!/bin/awk -F: -f -- /etc/passwd

followed by some awk code

James Brown
  • 34,397
  • 6
  • 36
  • 56
  • Looks like the issue is with different Linux/Unix systems not passing shebang arguments consistently. This post has some suggested workarounds that would work across various systems: https://stackoverflow.com/questions/4303128/how-to-use-multiple-arguments-for-awk-with-a-shebang-i-e – antun Apr 03 '20 at 02:12

2 Answers2

4

Many systems allow only a single argument in a shebang line, so everything after the space is passed as one argument.

However, you can set FS and even ARGV in your script's BEGIN block, like this:

#!/bin/awk -f              # using the #!/bin/awk -f
BEGIN {
    FS=":"                 # always use : as a field separator
    ARGC=2
    ARGV[1]="/etc/passwd"  # always run on the same file
}
$3==0 {                    # followed by some awk code
    print $1
}

Run it:

$ chmod u+x program.awk
$ ./program.awk
root
Toby Speight
  • 25,191
  • 47
  • 61
  • 93
James Brown
  • 34,397
  • 6
  • 36
  • 56
2

Never use a shebang to call awk as that has no worthwhile benefit over simply calling awk within your shell script but robs you of the ability to separate arguments passed to your shell script into values for the shell to process, values for awk to process use -v, values for awk to process using assignments at the end of the script and file names for awk to run on.

Just write:

#!/usr/bin/env bash
awk -F':' '
whatever
' /etc/passwd

so that if you had to you could trivially tweak it to:

#!/usr/bin/env bash
sort "$1" |
awk -F':' -v foo="$2" '
whatever
' - FS="$3" "$4"

or whatever else you need to do to use the arguments passed to your shell script most appropriately and make enhancements (e.g. add initial sorting of the input) without having to change the callers of your script.

Ed Morton
  • 172,331
  • 17
  • 70
  • 167
  • This "robbery" claim is not actually true, at least with GNU awk, mawk, and original-awk. `-F` works as expected. `-v var=value` var is usable anywhere in the awk script, including in a BEGIN block. When using an arg like `var=value` without `-v`, `var` is usable anywhere **except** a BEGIN block, same as when running awk in a shell script or on a shell command line. Filename args are used as normal by awk. I didn't test all of the other awk cmd line options but for the handful I tested, argument handling behaviour in a `#!/usr/bin/awk -f` script seems identical to just running awk in shell. – cas Mar 08 '22 at 15:20
  • For example: `#!/usr/bin/original-awk -f BEGIN { printf "foo=%s, bar=%s\n", foo, bar}; { print FILENAME ": " foo, bar}; END { printf "foo=%s, bar=%s\n", foo, bar}`. Run as, e.g., `/tmp/test.awk -F, -v foo=2 bar=3 file*.txt`. Even if the claim were true, it would be like claiming that you shouldn't use #!/bin/sh or /bin/bash etc scripts because the script can't use the shell's own options like `-c`, `-l`, etc. – cas Mar 08 '22 at 15:22
  • I have avoided commenting on your posts for far longer than you have done for me. But I can't stay silent when you make & link to the same incorrect claim again. I had previously assumed that you were correct when you made this claim, but I tested it tonight and it was incorrect. Maybe it was correct in the past (unlikely, due to mawk and original-awk working), but it's certainly not correct now. I suspect you think it's a problem because you ran into problems with abusing /usr/bin/env before env got the `-S` option. So chalk it up to yet another reason why #!/usr/bin/env is a bad idea. – cas Mar 08 '22 at 15:56
  • My comment **directly** addresses your claim: that an awk shebang *'robs you of the ability to [...irrelevant stuff about shell...], values for awk to process use -v, values for awk to process using assignments at the end of the script and file names for awk to run on.'*. Using #!/usr/bin/awk -f robs you of exactly **none** of these things. – cas Mar 08 '22 at 15:59
  • Again you are missing the point, arguing against something that was not in any way what I'm saying, and have literally provided proof in your comments that what I AM saying is 100% accurate. – Ed Morton Mar 08 '22 at 16:03
  • I said `... robs you of the ability to separate arguments passed to your shell script into values for the shell to process...` and you posted a call to a script that requires all arguments to the script to be arguments for awk to process with no way for them to be processed by shell, require all arguments to be awk syntax so you couldn't replace the guts of the command with perl or add some additional unix commands where appropriate or anything else without changing everywhere it's called and declared QED. smh... – Ed Morton Mar 08 '22 at 16:12