我使用的命令行应用程序本质上是 bash shell 脚本的集合。该应用程序被编写为可以在 BSD/OSX 和 Linux 上运行。其中一个脚本依赖于 awk。它包含两个 awk 命令:一个为 nawk(标准 BSD awk 实现)编写,另一个为 gawk(GNU awk 实现)编写。
所讨论的两个 awk 命令与不同环境不交叉兼容;特别是当使用 gawk 运行时 nawk 命令会失败。该脚本检查内核名称(即uname -s
)以确定主机环境,然后运行适当的 awk 命令。不过,我更喜欢在安装了 GNU 核心实用程序的 Mac OS X 上工作,因此脚本无法正确运行。
在思考如何最好地修复这个错误的过程中,我突然想到,如果能够以编程方式区分常见命令行实用程序的不同风格,最好是以相对健壮和可移植的方式来区分,那就太好了。
我注意到 nawk 不接受“-V”标志来打印版本信息,所以我认为类似以下的内容应该有效:
awk -V &>/dev/null && echo gawk || echo nawk
另一种变化可能是:
awk -Wversion &>/dev/null && echo gawk || echo nawk
这似乎适用于我的两个测试环境(OS X 和 CentOS)。这是我的问题:
- 这是最好的方法吗?
- 有没有办法扩展它来处理 awk 的其他变体(例如 mawk、jawk 等)?
- 是否值得担心其他版本的 awk?
我还应该提到我对 awk 知之甚少。
答案1
if awk --version 2>&1 | grep -q "GNU Awk"
then
awk 'BEGIN {print "I am GNU Awk"}'
elif awk -Wv 2>&1 | grep -q "mawk"
then
awk 'BEGIN {print "I am mawk"}'
else
awk 'BEGIN {print "I might be nawk, might not be"}'
fi
或者,test is awk 是一个符号链接:
awk=$( command -v awk )
[[ -L $awk ]] && readlink $awk # make some decision about the result of that
答案2
尝试使用该which
命令并使用其退出代码。
which nawk
if [[ $? == 0 ]]; then
command="nawk"
else
command="gawk"
fi
然后格式化脚本以使用变量作为命令
$command '{print $1}`
将被读作
nawk '{print $1}`
如果which
找到nawk。否则它会使用gawk
答案3
GNU Awk 通常安装为gawk
,并awk
在默认使用 GNU 的系统上作为其符号链接。我猜想 BSD 和 OS X 系统就是这种情况,因为它们已经有自己的awk
.
if gawk '{ exit; }' < /dev/null 2> /dev/null
then
echo "gawk available"
else
echo "gawk not available"
fi
答案4
我可能会尝试滥用 autoconf 中的 AC_PROG_AWK m4 宏来选择一个,并对它们进行适当的排序。但这可能有点过分了