如何使用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,它甚至没有适当的文件。
对于它的作用有一个粗略的一致意见: 和\n
和exec
它。 这个假设就是这个之间的一切!
而\n
是翻译的绝对path。 如果它包含空白,会发生什么事情没有共识。
- 有些操作系统只是把整个事情当成path。 毕竟,在大多数操作系统中,path中的空格或破折号是合法的。
- 一些操作系统以空格分割,将第一部分作为解释器的path,其余部分作为单独的参数。
- 一些操作系统在第一个空白处分割,把前面的部分作为中间层的path,其余部分作为单个参数(这就是你所看到的)。
- 有些人甚至根本不支持三帮线。
值得庆幸的是,1.和4.似乎已经消失了,但是3.相当普遍,所以你根本不能依靠能够通过一个以上的论证。
由于命令的位置也没有在POSIX或SUS中指定,通常通过将可执行文件的名称传递给env
来使用该单个参数,以便可以确定可执行文件的位置; 例如:
#!/usr/bin/env gawk
[很明显,这仍然为env
了一个特定的path,但是只有很less的系统存在于/bin
,所以这通常是安全的。 env
的位置比gawk
的位置更为标准化,甚至更糟糕的是python
, ruby
或spidermonkey
。]
这意味着你根本不能使用任何参数。
在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
为什么不使用bash
和gawk
本身,跳过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 }
(当然也可以用sed
或tail
来实现,但是我认为只有bash
和gawk
本身才有某种美感)
对于一个可移植的解决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在脚本上做了可变的扩展,所以你必须引用每个$(如脚本的第二行所做的),而且可能不止于此。