#! /bin/sh -
if : ^ false; then : fine, POSIX system by default
else
# cover Solaris 10 or older. ": ^ false" returns false
# in the Bourne shell as ^ is an alias for | there for
# compatibility with the Thompson shell.
PATH=`getconf PATH`:$PATH; export PATH
exec /usr/xpg4/bin/sh - "$0" ${1+"$@"}
fi
# rest of script
我认为主要是因为:
实施之间的行为差异很大。有关所有详细信息,请参阅https://www.in-ulm.de/~mascheck/various/shebang/。
然而,它现在可以指定大多数类 Unix 实现的最小子集:比如
#! *[^ ]+( +[^ ]+)?\n
(只有一个或两个单词中的可移植文件名字符集中的字符)其中第一个单词是本机可执行文件的绝对路径,事情不是如果可执行文件是 setuid/setgid,则太长并且行为未指定,并且实现定义了解释器路径或脚本路径是否传递argv[0]
给解释器。POSIX 并没有指定可执行文件的路径。几个系统在
/bin
/中具有 pre-POSIX 实用程序,/usr/bin
并且在其他地方具有 POSIX 实用程序(例如在 Solaris 10 上,其中/bin/sh
是 Bourne shell 而 POSIX 位于/usr/xpg4/bin
;Solaris 11 将其替换为更符合 POSIX 的 ksh93,但其他大多数中的工具/bin
仍然是古老的非 POSIX 工具)。有些系统不是 POSIX 系统,但具有 POSIX 模式/仿真。所有 POSIX 要求是有一个记录的环境,系统在其中运行 POSIXly。例如,参见 Windows+Cygwin。实际上,在 Windows+Cygwin 中,当脚本由 cygwin 应用程序调用时,she-bang 会受到尊重,而不是由本机 Windows 应用程序调用。
因此,即使 POSIX 指定了 shebang 机制,它也不能用于编写 POSIX
sh
// ... 脚本(另请注意,shebang 机制不能用于编写可靠的sed
/脚本,因为它不允许传递选项结束标记)。awk
sed
awk
现在它未指定的事实并不意味着你不能使用它(好吧,它说
#!
如果你希望它只是一个常规评论而不是一个she-bang,那么你不应该从第一行开始),但是如果你这样做,POSIX 不给你任何保证。根据我的经验,使用 shebangs 比使用 POSIX 编写 shell 脚本的方式为您提供更多的可移植性保证:放弃 she-bang,以 POSIX
sh
语法编写脚本,并希望调用脚本的任何内容都调用符合 POSIX 的脚本sh
,即如果您知道脚本将在正确的环境中由正确的工具调用,那么很好,但不是这样。您可能必须执行以下操作:
如果您想移植到 Windows+Cygwin,您可能必须使用
.bat
或.ps1
扩展名命名您的文件,并使用一些类似的技巧cmd.exe
来powershell.exe
调用sh
同一文件上的 cygwin。你看的不够深入。
早在 1980 年代,这种机制实际上并没有标准化。尽管 Dennis Ritchie 已经实施了它,但该实施尚未在 AT&T 的宇宙中向公众传播。它实际上只在 BSD 中公开可用并为人所知;在 AT&T Unix 上不可用的可执行 shell 脚本。因此,将其标准化是不合理的。这个当代的 doco 就是这种事态的例证,它是许多这样的例子之一:
——斯蒂芬·弗雷德(1988 年)。“在 System X Release Y 上编程”。澳大利亚 Unix 系统用户组通讯。第 9 卷,第 4 期。111.这里重要的一点是您正在查看 shell,而可执行的 shell 脚本的存在实际上是
exec…()
函数的问题。shell 所做的包括可执行脚本机制的前身,即使在今天仍然可以在某些 shell 中找到(现在也被强制用于exec…p()
功能子集),并且有些误导。在这方面,标准需要解决的是exec…()
解释脚本如何工作,而在最初创建 POSIX 时,它根本无法在目标操作系统的主要部分中工作。一个从属的问题是为什么此后没有标准化,尤其是在 1990 年代之交,脚本解释器的幻数机制已经在宇宙的 AT&T 方面向公众传播并已
—exec…()
在系统 5 接口定义中记录下来:exec
. System V 接口定义。第 1 卷。1991 年。不幸的是,今天的行为几乎与 1980 年代一样大相径庭,并且没有真正常见的行为可以标准化。一些 Unices(例如著名的 HP-UX 和 FreeBSD)不支持将脚本作为脚本的解释器。第一行是由空格分隔的一个、两个还是多个元素,这在 MacOS(以及 2005 之前的 FreeBSD 版本)和其他之间有所不同。支持的最大路径长度会有所不同。
␀
POSIX 可移植文件名字符集之外的字符和前导和尾随空格一样棘手。第 0、第 1 和第 2 个参数的最终结果也很棘手,系统之间存在显着差异。一些当前符合 POSIX 但不符合-Unix 系统仍然不支持任何这样的机制,并且强制它会将它们转换为不再符合 POSIX 标准。进一步阅读
script
. NetBSD 杂项信息手册。2005-05-06。正如其他一些答案所指出的那样,实现方式各不相同。这使得标准化和保持与现有脚本的向后兼容性变得困难。即使对于现代 POSIX 系统也是如此。例如,Linux 没有用空格完全标记 shebang 行。macOS 不允许脚本解释器成为另一个脚本。
另见http://en.wikipedia.org/wiki/Shebang_(Unix)#Portability