在尝试破译当前公司前员工编写的一些脚本时,在许多脚本中,我遇到了以下语句,这些语句将变量分配给某些命令,如下所示:
CAT=cat
GREP=grep
SED=sed
在脚本的后面,我看到他们使用了这些变量而不是常规命令:
$GREP -v "^#" `dirname $0`/abcdfilename | while read line
do
<some loop operations>
done
我不明白使用这个变量而不是grep
直接使用有什么意义。我的问题是:
- 以这种方式执行 grep 或 sed (在我们的例子中)有什么意义吗?
- 这是某人试图编写脚本以使其他人更难理解的结果吗?
- 或者这只是糟糕脚本的一个例子?
答案1
标准命令在系统上有不同的实现。与 Solaris 10 及更早版本中一样,您拥有/bin/sh
旧的 Bourne shell 和/usr/xpg4/bin/sh
POSIX 兼容 shell。或者在 OSX 上,调用时使用 BSD sed sed
,调用时使用 GNU sed gsed
。您可以选择要在脚本中使用的实现。
因此,当您使用变量时,更改脚本中的实现会更容易。当您需要 GNU sed 时:
SED=gsed
如果您不使用变量,则必须替换sed
脚本中所有出现的 。尽管您可以轻松做到这一点,但这被认为是不好的编程习惯。
答案2
有一种观点认为,将整个脚本中重复使用的几乎所有内容都变成变量,因为这样您就可以重新定义它一次,并让它影响脚本的其余部分。
您可能会说,使用简单的 sed 搜索/替换基本上可以完成相同的事情,但许多用户对搜索/替换持谨慎态度,因为意外替换您不打算替换的内容并不难。
事实上,我建议对他们现有的版本进行这样的改进:
GREP=${GREP:-/bin/grep}
这意味着 GREP 将被设置为用户在 shell 中设置的任何内容,或者如果未设置,则设置为 /bin/grep
这样用户就可以即时覆盖“grep”。
$ export GREP=/bin/fgrep
$ ./path/to/script.sh
答案3
这可能是过早优化的一个例子。
该机器有多少种选择,或者任何机器有用于sed,grep, 和awk?我敢打赌普遍平均值接近 1.0。给定特定机器上的两个选择,实现不同导致脚本在 PATH 上找到的版本失败而与另一个版本一起工作的可能性有多大?如果确实发生这种情况,解决方案更有可能是更改脚本还是路径?如果更改脚本被证明是答案,那么找到至少一次调用的可能性有多大?grep代替$GREP?该套牌的堆放不需要任何间接性,并且在需要时也不会按预期工作。
我不会对抗这种文化。如果您的商店有一些偏好$GREP或者/usr/bin/grep要不就grep,我可能会一起去相处。否则,KISS:避免间接,直到需要它出现为止。