如何使用shebang(即#!)为awk使用多个参数?

Han*_*örr 114 unix shell awk shebang gawk

我想用shebang 执行一个gawk脚本--re-interval."幼稚"的方法

#!/usr/bin/gawk --re-interval -f
... awk script goes here
Run Code Online (Sandbox Code Playgroud)

不起作用,因为gawk是用第一个参数调用的"--re-interval -f"(不是在空白处分开),它不明白.有解决方法吗?

当然你可以不直接调用gawk,而是将它包装成一个分割第一个参数的shell脚本,或者创建一个shell脚本,然后调用gawk并将脚本放到另一个文件中,但我想知道是否有某种方法可以做这在一个文件中.

shebang行的行为因系统而异 - 至少在Cygwin中它不会通过空格分割参数.我只关心如何在一个行为类似的系统上做到这一点; 该脚本不是便携式的.

Jör*_*tag 156

shebang系列从未被指定为POSIX,SUS,LSB或任何其他规范的一部分.AFAIK,它甚至没有被正确记录.

关于什么它粗糙的共识:取之间的一切!\nexec它.假设是!和之间的所有内容都是\n解释器的完整绝对路径.如果它包含空格,则没有达成共识.

  1. 有些操作系统只是将整个事物视为路径.毕竟,在大多数操作系统中,空格或破折号在路径中是合法的.
  2. 某些操作系统在空白处拆分,并将第一部分视为解释器的路径,其余部分作为单独的参数.
  3. 某些操作系统在第一个空格处分开,并将前部分视为interpeter的路径,将其余部分视为单个参数(这是您所看到的).
  4. 有些人甚至不支持家当线在所有.

值得庆幸的是,1.和4.似乎已经消亡,但是3.相当普遍,所以你根本不能依靠能够传递多个参数.

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

#!/usr/bin/env gawk
Run Code Online (Sandbox Code Playgroud)

[显然,这仍然是一个特定的路径env,但它只存在很少的系统/bin,所以这通常是安全的.的位置env是很多比的位置更加规范gawk或者类似的东西更糟糕pythonrubyspidermonkey]

这意味着,你不能真正使用任何参数在所有.

  • @Kaz:是的,但是由于许多二进制文件的路径都没有标准化,你用掉了一个参数`#!/ usr/bin/env ruby​​`或者喜欢的. (5认同)
  • FreeBSD 的 env 有一个 `-S` 开关,它在这里有帮助,但它在我的 Linux `env` 上不存在,我怀疑在 gygwin 上也不可用。@hstoerr,其他情况不同的用户可能会稍后阅读您的问题,因此通常可移植的答案更可取,即使您现在不需要可移植性。 (2认同)
  • 所以我们不能在shebang中使用参数.但是如果我们需要通过任何必要的方式进行论证呢 我猜测解决方案是编写一个包含`#!/ bin/sh`和`/ usr/bin/env gawk --re-interval -f my-script.awk`的包装shell脚本.那是对的吗? (2认同)
  • @Pacerier:更改POSIX规范并等待20 - 30年,直到所有系统都更新为符合规范. (2认同)

Aar*_*aid 24

这似乎对我有用(g)awk.

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"


# The real awk program starts here
{ print $0 }
Run Code Online (Sandbox Code Playgroud)

请注意#!运行/bin/sh,因此首先将此脚本解释为shell脚本.

起初,我只是尝试过"exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@",但是awk将其视为一个命令并无条件地打印出每一行输入.这就是为什么我放入arbitrary_long_name==0- 它应该一直失败.你可以用一些乱码的字符串替换它.基本上,我在awk中寻找一个不会对shell脚本产生负面影响的错误条件.

在shell脚本中,arbitrary_long_name==0定义一个被调用的变量arbitrary_long_name并将其设置为等于=0.


ℝap*_*ink 12

我遇到了同样的问题,没有明显的解决方案,因为在shebang处理空白的方式(至少在Linux上).

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

例如,你不能拥有

#!/usr/bin/foo -i -f
Run Code Online (Sandbox Code Playgroud)

但你可以拥有

#!/usr/bin/foo -if
Run Code Online (Sandbox Code Playgroud)

显然,只有当选项具有短的等价物并且不带参数时才有效.


uno*_*ode 12

尽管不是完全可移植,但是从coreutils 8.30开始,根据其文档,您将可以使用:

#!/usr/bin/env -S command arg1 arg2 ...
Run Code Online (Sandbox Code Playgroud)

因此给出:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too
Run Code Online (Sandbox Code Playgroud)

你会得到:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'
Run Code Online (Sandbox Code Playgroud)

如果您好奇的话,showargs是:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
    echo "\$$i is '$arg'"
    i=$((i+1))
done
Run Code Online (Sandbox Code Playgroud)

原始答案在这里


Mor*_*itz 11

在Cygwin和Linux下,shebang路径之后的所有内容都被解析为程序作为一个参数.

通过使用awkshebang中的另一个脚本可以解决这个问题:

#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}
Run Code Online (Sandbox Code Playgroud)

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

  • 如果您已将参数传递给脚本,这将不起作用 (2认同)