如何使用awb与shebang(即#!)的多个参数?

我想执行一个gawk脚本--re-interval使用shebang。 “天真”的做法

 #!/usr/bin/gawk --re-interval -f ... awk script goes here 

不起作用,因为gawk被第一个参数"--re-interval -f" (不是分割在空白周围)调用,它不理解。 有没有解决方法?

当然,你可以不直接调用gawk,而是将其封装到一个shell脚本中,以分裂第一个参数,或者创build一个shell脚本,然后调用gawk并将脚本放到另一个文件中,但是我想知道是否有一些方法可以做这在一个文件中。

shebang行的行为在系统之间是不同的 – 至less在Cygwin中它不会用空格分隔参数。 我只是在乎如何在一个像这样的系统上做到这一点; 该脚本并不意味着可移植。

这似乎适用于(g)awk的我。

 #!/bin/sh arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@" # The real awk program starts here { print $0 } 

注意#! 运行/bin/sh ,所以这个脚本首先被解释为一个shell脚本。

起初,我只是尝试了"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@" ,但是awk把它作为一个命令并打印出每行input无条件的。 这就是为什么我把arbitrary_long_name==0 – 它应该总是失败。 你可以用一些乱码stringreplace它。 基本上,我在awk中寻找一个不会对shell脚本产生不利影响的错误条件。

在shell脚本中, arbitrary_long_name==0定义了一个名为“ arbitrary_long_name的variables,并将其设置为=0

从未被指定为POSIX,SUS,LSB或任何其他规范的一部分。 AFAIK,它甚至没有适当的文件。

对于它的作用有一个粗略的一致意见: 和\nexec它。 这个假设就是这个之间的一切!\n是翻译的绝对path。 如果它包含空白,会发生什么事情没有共识。

  1. 有些操作系统只是把整个事情当成path。 毕竟,在大多数操作系统中,path中的空格或破折号是合法的。
  2. 一些操作系统以空格分割,将第一部分作为解释器的path,其余部分作为单独的参数。
  3. 一些操作系统在第一个空白处分割,把前面的部分作为中间层的path,其余部分作为单个参数(这就是你所看到的)。
  4. 有些人甚至根本不支持三帮线。

值得庆幸的是,1.和4.似乎已经消失了,但是3.相当普遍,所以你根本不能依靠能够通过一个以上的论证。

由于命令的位置也没有在POSIX或SUS中指定,通常通过将可执行文件的名称传递给env来使用该单个参数,以便可以确定可执行文件的位置; 例如:

 #!/usr/bin/env gawk 

[很明显,这仍然env了一个特定的path,但是只有很less的系统存在于/bin ,所以这通常是安全的。 env的位置比gawk的位置更为标准化,甚至更糟糕的是pythonrubyspidermonkey 。]

这意味着你根本不能使用任何参数。

在Cygwin和Linux下,shebangpath之后的所有东西都作为一个参数被parsing到程序中。

有可能通过在shebang中使用另一个awk脚本来解决这个问题:

 #!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit} 

这将执行{system("/usr/bin/gawk --re-interval -f " FILENAME); exit} {system("/usr/bin/gawk --re-interval -f " FILENAME); exit} awk。
这将在您的系统shell中执行/usr/bin/gawk --re-interval -f path/to/your/script.awk

我遇到了同样的问题,因为在一个shebang(至less在Linux上)处理空白的方式没有明显的解决scheme。

然而,你可以在一个shebang中传递几个选项,只要它们是短的选项 ,并且可以连接 (GNU方式)。

例如,你不能拥有

 #!/usr/bin/foo -i -f 

但你可以有

 #!/usr/bin/foo -if 

显然,只有当期权具有短期的等同性而且没有参数时才有效。

在gawk手册(http://www.gnu.org/manual/gawk/gawk.html)中,第1.14节的末尾指出,从shebang行运行gawk时应该只使用一个参数。; 它说,操作系统将把path后面的所有东西都当作一个参数来处理。 也许还有另一种方法来指定--re-interval选项? 也许你的脚本可以在shebang行中引用你的shell,运行gawk作为一个命令,并将你的脚本文本作为“here文档”包含进来。

 #!/bin/sh ''':' exec YourProg -some_options "$0" "$@" ''' # The above shell shabang trick is more portable than /usr/bin/env 

为什么不使用bashgawk本身,跳过shebang,读取脚本,并将其作为文件传递给gawk [--with-whatever-number-of-params-you-need]的第二个实例gawk [--with-whatever-number-of-params-you-need]

 #!/bin/bash gawk --re-interval -f <(gawk 'NR>3' $0 ) exit { print "Program body goes here" print $1 } 

(当然也可以用sedtail来实现,但是我认为只有bashgawk本身才有某种美感)

对于一个可移植的解决scheme,使用awk而不是gawk ,用你的shebang调用标准的BOURNE shell( /bin/sh ),直接调用awk ,在命令行上传递程序作为here文件,而不是通过stdin:

 #!/bin/sh gawk --re-interval <<<EOF PROGRAM HERE EOF 

注意: awk没有-f参数。 这使得stdin可以从awk读取input。 假设你已经安装了gawk并且安装了你的PATH ,那就实现了所有我认为你正在试图用你原来的例子(假设你想要的文件内容是awk脚本而不是input,我认为你的shebang方法会处理它作为)。

只是为了好玩:有一个很奇怪的解决scheme,通过文件描述符3和4重新路由stdin和程序。您也可以为脚本创build一个临时文件。

 #!/bin/bash exec 3>&0 exec <<-EOF 4>&0 BEGIN {print "HALLO"} {print \$1} EOF gawk --re-interval -f <(cat 0>&4) 0>&3 

有一件事令人讨厌:shell在脚本上做了可变的扩展,所以你必须引用每个$(如脚本的第二行所做的),而且可能不止于此。