分发脚本:我应该为shebang 使用/bin/gawk 还是/usr/bin/gawk?

12 awk env shebang

gawk 通常是在 /bin 还是 /usr/bin 中?我会去,#!/usr/bin/env gawk但后来我不能使用参数。现在我正在使用#!/bin/gawk -f. 脚本很长,包含很多单引号,并与标准输入一起使用。

GNU Awk 手册有部分 1.1.4 Executable awk Programs在它的示例中使用 #!/bin/awk 但接着说:

请注意,在许多系统上awk可能会发现 in/usr/bin而不是 in /bin。买者自负。

大多数人做什么?我读过sed 应该在 /bin 中标准化,而 perl 应该在 /usr/bin 中标准化(与 sed 链接相同的页面,但他们不会让我为这篇文章制作第三个链接)。awk/gawk 怎么样?有谁知道哪个更常见或更受欢迎?

Gil*_*il' 15

如果您不需要将参数传递给命令,那么#!/usr/bin/env gawk就是要走的路,但是许多内核(包括 Linux)只接受一个参数给 shebang 程序。

否则,您可以制作一个既是 shell 包装器又是 awk 脚本的多语言程序。这是 awk 的一个。

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here
Run Code Online (Sandbox Code Playgroud)

外壳解析:

  • true + /;true带有两个惰性参数+/.
  • 对 的调用gawk。这可以是任何不包含换行符和写斜杠的 shell 片段\/(shell 不介意,除了引号内)。
    该调用使用execgawk 替换 shell,而不是将 gawk 作为子进程执行。
  • exit;— 退出 shell,以防找不到 gawk。之后的任何内容都将被忽略,除了它应该是有效的 shell 语法,以防 shell 在开始执行之前尝试解析整行。

awk 解析:

  • 斜线之间的位是正则表达式。
  • true + /REGEX/- 一个条件。true是一个未定义的变量,所以它的数值是 0,这并不重要。
  • {} — 如果上述条件成立,则什么都不做。


for*_*sck 7

Shebang本来就不是那么灵活的。在某些情况下,使用第二个参数可能会起作用,我认为 FreeBSD 就是其中之一。

gawk 和操作系统附带的大多数实用程序预计将在 /usr/bin/.

在较早的 UNIX 时代,/usr/通过 NFS 或一些较便宜的介质进行安装以节省本地磁盘空间和每个工作站的成本是很常见的。/bin/应该拥有在单用户模式下启动所需的一切。由于/usr/没有安装在可靠的媒体上,/bin/包含足够的实用程序以使其对一般管理和故障排除足够友好。

这最初是在 Linux 中继承的,但由于磁盘空间不再是问题,并且在大多数情况下/usr/在根文件系统中,当前的趋势是将所有内容都移入/usr/bin(至少在 Linux 世界中)。因此,预计发行版安装的大多数实用程序都可以在那里找到。连最起码的公共事业,如cprmls等(当然,目前还没有)。

关于shebang的选择。传统上,这是管理员或用户必须根据他们的环境进行编辑的内容。就开发人员所知,在其他人的系统中,解释器可以位于文件系统中的任何位置(例如/usr/local/bin/opt/gawk-4.0.1/bin)。正确打包的脚本(rpm、deb 等)要么依赖于发行版包(即解释器具有已知位置),要么依赖于在安装过程中设置正确 hashbang 的配置脚本。


Mar*_*elo 7

吉尔斯提出的解决方案确实是一个非常好的方法(终于在他的帖子中享有投票权:))。

在任何情况下,据我了解该exec命令,它使exit后面的权利变得不必要,实际上无法访问,因为 shell 进程被awk.

此外,为了允许awk脚本访问其调用参数,我建议对提议的解决方案进行一些更改:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here
Run Code Online (Sandbox Code Playgroud)

-a "$0"允许脚本访问其调用的名称,否则将永远得到awkgawk访问时,ARGV[0]变量。类似地,"$@"允许脚本访问ARGV[1...N]数组中剩余的参数,而--前面的 it 允许脚本接收-<something>参数而不用 gawk 解释它们是为它准备的。

要记住/考虑的一件事是在脚本程序块exit(0);的末尾添加一条语句,否则会威胁到作为输入文件传递给脚本的所有参数。(请注意,它与我们从行中删除的语句完全无关,这是一个无法访问的 shell 语句,而这个建议的退出在 awk 代码中)。BEGIN { ... }awkawkexittrue + ...