渡されたすべての引数を要約する次のシェルスクリプトがあります(スペースで区切られています)。
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サーバーで同じことを試みると、動作しますがbash
動作sh
しないスクリプトを実行します。次のエラーが発生します。
sum: '+=': No such file or directory
sum: arg: No such file or directory
なぜそんなことですか?どうすれば解決できますか?
答え1
算術評価は、(( ... ))
実装された標準のPOSIXシェル構文の拡張ですbash
。ほとんどのsh
シェルはこの構文を理解していません。
代わりに算術置換を使用してください。sum=$(( sum + arg ))
非標準を実装していないシェルでは、コマンドはネストされた(( ... ))
サブシェル(( sum += arg ))
として解釈され、sum
2つの引数+=
で呼び出されます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
また、スクリプトがいつ失敗するかを確認できるようにするか、デバッグフラグをより頻繁に使用する必要があります。
Bash とシェルスクリプトの詳細情報とヒントについては、以下をお勧めします。