我有以下 shell 脚本,它总结了传递给它的所有参数(以空格分隔):
sum=0
for arg in "$@"; do
(( sum += arg ))
done
echo $sum
我已将其保存为SumAll.sh
.因此,它的功能应该如下:
sh SumAll.sh 2 4 6 8
20
或者
bash SumAll.sh 1 -2 3 -3
-1
两者都可以在我的本地计算机(MacBook)上运行,但是当我在 Linux 服务器中尝试相同的操作时,运行脚本 withbash
可以,但 withsh
不起作用。我收到以下错误:
sum: '+=': No such file or directory
sum: arg: No such file or directory
这是为什么?我该如何解决它?
答案1
算术评估(( ... ))
是对所实现的标准 POSIX shell 语法的扩展bash
。大多数sh
shell 无法理解该语法。
使用算术替换代替:sum=$(( sum + arg ))
在未实现非标准 的 shell 中(( ... ))
,您的(( sum += arg ))
命令将被解释为嵌套子 shell,并使用sum
两个参数+=
和调用该命令arg
。
在 macOS 上,sum
是一个计算文件校验和的实用程序(请参阅),并且无法找到man sum
文件(这就是您收到该特定错误的原因)。+=
arg
答案2
使用外壳检查。
使用您的脚本的示例:
#!/bin/bash
sum=0
for arg in "$@"; do
(( sum += arg ))
done
echo $sum
结果:
$ shellcheck myscript
Line 6:
echo $sum
^-- SC2086: Double quote to prevent globbing and word splitting.
Did you mean: (apply this, apply all SC2086)
echo "$sum"
正如您所看到的,这是可行的,但是如果您像以前一样使用 sh :
#!/bin/sh
sum=0
for arg in "$@"; do
(( sum += arg ))
done
echo $sum
结果:
$ shellcheck myscript
Line 4:
(( sum += arg ))
^-- SC2039: In POSIX sh, standalone ((..)) is undefined.
Line 6:
echo $sum
^-- SC2086: Double quote to prevent globbing and word splitting.
Did you mean: (apply this, apply all SC2086)
echo "$sum"
SC2039
由于错误(这是本例中的第一个错误),这在这里不起作用。
虽然很明显,但您需要记住这一点sh
并且bash
在语法上有一些差异。所以这就是它不起作用的主要原因。 (正如 @kusalananda 在他的回答中详细说明的那样)
您还应该-x
更频繁地使用 或 debug 标志,这样您就可以看到脚本失败的内容以及失败的时刻。
有关 bash 和 shell 脚本编写的更多信息和技巧,我建议:
-巴什圣经