我在 Mac 上安装了 BSD(默认)和 GNU Awk 实现(后者是使用gawk
而不是仅仅 来调用的awk
),并且我有一个包含如下内容的 shell 脚本:
awk -v maxLen=72 '
.
.
.
' "$1" > "$2"
现在到了棘手的部分。要正常工作,脚本必须使用 GNU Awk。这意味着我至少有两个选择:1) 修改脚本的第一行,以便使用 而不是gawk
,awk
2) 为 GNU Awk 创建系统范围的别名,以便使用 来调用它awk
。gawk
但我更愿意避免这两种选择,而是使用包装器来执行脚本。也就是说,而不是
./script.sh input.txt output.txt
我更喜欢
sed -e 's/awk/gawk/' script.sh
然后以某种方式将输出传递给 Zsh。有人告诉我这可以使用 Zsh 进程替换功能来实现,但是如何实现呢?
假设
awk
在 macOS 上使用 Homebrew 安装了 GNU,则gawk
软件包在安装结束时会显示以下内容(看看brew info gawk
您是否错过了什么):PATH
让脚本在运行命令之前进行修改awk
:awk
将在 中搜索该命令$PATH
,如果该路径存在,则将在 中找到修改后的可执行文件路径/opt/homebrew/opt/gawk/libexec/gnubin
。在该路径不存在的系统上,它将使用它能找到的任何其他名为 的命令awk
。除了
awk
上述脚本中的命令之外,您还可以使用exec "$@"
,这将使脚本成为您所建议的包装器:请注意,在某些 macOS 系统上,Homebrew 使用
/usr/local/homebrew
而不是/opt/homebrew
。如果您的 Homebrew 安装正确,您应该能够使用$HOMEBREW_PREFIX
该部分路径。awk
还要注意的是,如果系统上没有安装 GNU,这将默认使用非 GNU 。为了解决这个问题,请在脚本中运行命令之前测试路径中awk
是否存在(使用),或者直接使用命令而不是。gawk
awk
command -v gawk
gawk
awk
您可以执行以下操作:
或者:
小心它也会
echo The hawk squawked | /usr/bin/awk 1
变成echo The hgawk squgawked | /usr/bin/gawk 1
。相反,使用
zsh
的multios
功能,您可以执行以下操作:或者您可以使用
perl
它awk
可以做任何awk
实现可以做的事情,甚至更多,并且它只有一种实现(当然有几个版本,但 API 相对稳定并且通常在不同版本之间向后兼容)。