在这种情况下,为什么我能够将参数传递给 /usr/bin/env ?

在这种情况下,为什么我能够将参数传递给 /usr/bin/env ?

我读到另一个答案我无法将参数传递给解释器,而不是我所提供的/usr/bin/env

另一个潜在的问题是,该#!/usr/bin/env技巧不允许您将参数传递给解释器(除了隐式传递的脚本名称之外)。

然而,看起来我能够做到,因为awk当我不给它标志时它会被破坏-f,而当我给它标志时它会被修复-f,同时使用/usr/bin/env

首先,没有-f标志:

$ cat wrap_in_quotes
#!/usr/bin/env awk
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
awk: syntax error at source line 1
 context is
     >>> . <<< /wrap_in_quotes
awk: bailing out at source line 1

二、带-f旗:

$ vim wrap_in_quotes
$ cat wrap_in_quotes
#!/usr/bin/env awk -f
# wrap each line in quotes
# usage: wrap_in_quotes [ file ... ]
{ print "\""$0"\"" }
$ echo foobar | ./wrap_in_quotes
"foobar"
  • 那么,如果根据链接答案我无法将标志传递给解释器,为什么我能够将标志传递-fawk

我在跑macOS

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.12.1
BuildVersion:   16B2657

答案1

一些 Unices,尤其是 macOS(以及 2005 年之前的 FreeBSD)将允许这样做,而 Linux 则不允许,但是……

如果使用env最新版本的 GNU coreutils 包 (8.30+) 中的实用程序,它有一个非标准-S选项,允许#!在行中提供多个参数。

相反的问题:使用 `#!/usr/bin/env command --argument` 的 Shebang 行在 Linux 上失败

答案2

你不能便携式的将多个参数传递给解释器。特别是,Linux 不支持它。

某些 Unix 变体确实支持 shebang 行上的多个参数。现代 macOS 系统和其他一些系统就是这种情况。看Sven Mascheck 的 shell 可移植性页面为一个Unix 变体比较表以及大量的历史信息。


如果您想要一个可移植的 awk 脚本,则没有巧妙的解决方案。#!/usr/bin/env#!/bin/sh是唯一在实践中可移植的 shebang 行:根据 Unix 变体,awk可能位于/bin/usr/bin,或位于其他一些位置(例如,/usr/xpg4/bin/awk在 Solaris 上获得 POSIX 行 - 中的行/usr/bin用于遗留应用程序)。由于#!/usr/bin/env awk -f不能移植,所以就只剩下#!/bin/sh. (/bin/sh可能是传统的 Bourne shell,而不是现代的 POSIX shell,但任何 Unix 平台在实践中都有一些东西。)这个想法是编写一个多语言sh,即解释为运行 awk 的指令并且 awk 解释为所需脚本的脚本。这甚至适用于无法识别 shebang 行但默认sh执行脚本的系统(一些古董 unice,或非 Unix 内核上的一些类 unix 用户区)。

#!/bin/sh
"exec" "awk" "-f" "$0" "$@" && 0 {}
… # awk script here

(如果担心古代统一的可移植性,请参阅斯文·马斯切克的页面支持"$@"并考虑使用${1+"$@"}。)

相关内容