Invoking a script, which has an awk shebang, with parameters (vars)

后端 未结 4 1882
梦毁少年i
梦毁少年i 2021-01-03 19:06

I have an awk script that I have defined thus:

#!/usr/bin/env awk
BEGIN { if (!len) len = 1; end = start + len }
{ for (i = start; i < end; i++) { print $         


        
相关标签:
4条回答
  • 2021-01-03 19:39

    Unfortunately, this is not easy to solve in a portable way. The standard technique looks like this (substitute /usr/bin/awk for your awk path):

    #!/usr/bin/awk -f
    
    BEGIN { if (!len) len = 1; end = start + len }
    { for (i = start; i < end; i++) { print $1 } }
    

    The hard-coded awk path and non-standard -f flag, makes this not portable across all *nixes. If you are only ever going to run your script on one machine, then this may work fine. However, to make a portable awk script, you will need to wrap it in a shell script. Here are two ways that you can do it in one file:

    The first way is standard and easy to read:

    #!/bin/sh
    
    awk '
    BEGIN { if (!len) len = 1; end = start + len }
    { for (i = start; i < end; i++) { print $1 } }
    ' "$@"
    

    Unfortunately, this falls short in two key ways:

    1. If your awk script contains a ' character, you will need to type it like this: '"'"' to "escape" it.
    2. If you are using a text editor with syntax highlighting, you will not get your awk script properly highlighted.

    Another solution, is to use sed to strip out the sh wrapper:

    #!/bin/sh
    exec awk "$(sed '1,2d' "$0")" "$@"
    
    BEGIN { if (!len) len = 1; end = start + len }
    { for (i = start; i < end; i++) { print $1 } }
    

    This is something like a two line shabang header. It calls awk using the file from line 3 down as the script argument. This allows you to keep your pretty syntax highlighting and you can still use ' characters to your heart's content. The two downsides I see are:

    1. Arguably this is non-intuitive to read.
    2. If you are using a code linter, it may not like this.
    0 讨论(0)
  • 2021-01-03 19:44

    Below is the answer for this problem -

    #!/bin/awk -f 
    
    0 讨论(0)
  • 2021-01-03 19:55

    env is the easiest way to handle this problem:

    #!/usr/bin/env -S awk -f
    

    to add more options, and to ensure no interference with your arguments, and awk's arguments:

    #!/usr/bin/env -S awk -F: -f ${_} --
    BEGIN {
        # delete argv[1], which == ENVIRON[_]
        delete ARGV[1]
    } # rest of my awk program
    

    as env has a POSIX standard, this shbang should get you around the difficulties of non-standard shbang implementations across unixen.

    EDIT

    after having written this I realized that '-S' is a non-POSIX compliant FreeBSD env extension. So shell wrapper is probably the way to go, unfortunate as that is.

    0 讨论(0)
  • 2021-01-03 19:56

    Try using:

    #!/usr/bin/awk -f
    

    as an interpreter

    0 讨论(0)
提交回复
热议问题