web-dev-qa-db-ja.com

$ @は数学のループで使用されます

コマンドライン引数として数値のリストを取得し、それらの数値の合計を出力するBashスクリプトを作成しようとしています。

したがって、スクリプトはscript.sh 1 555 22 122 66として実行され、それらをすべて合計します。それらを$@変数に渡してからループを実行する必要があることはわかっていますが、計算を行うために$@の内容をintに変換する方法がわかりません。私はこれをやろうとしました:

#!/bin/bash
for i in $@
do
    $@+$@
    echo "the total is `$@`"
done
1
DanMan3395

一般に、引数は、算術$((...))展開内で使用される場合、自動的に整数に変換されます。このループはすべての引数を合計します。

for x; do sum=$((sum+x)); done; echo "$sum"

Cプログラムがargv []配列を処理するときに、シェルはすべての引数を別々のメモリ位置にキャッシュします。シェルユーザーはその配列を直接処理する必要はありません。シェルはそれらを$ 1、$ 2、$ 3などに割り当てることで役立ちます。シェルは「$ @」などのリストも抽象化します。そして最後に、構文for xは、for x in "$@"がすべての引数をループするための省略形です。

これは、引数がゼロで始まらない10進数、ゼロで始まる8進数、または0xで始まる16進数であり、合計がオーバーフローしないことを前提としています(64ビットシステムでは2 ^ 63-1 )

このリスト:

$ ./script 12 021 0xab

200(小数の結果)を出力します。

8
Isaac

これは、次の方法で実現できます。

tr ' ' '+' <<<"$@" | bc

渡されたすべての引数を受け取り、空白を+記号に置き換えてから、それをbcにパイプします。

8
jesse_b

議論を一つずつ取ってください:

total=0
while [ -n "$1" ]; do
  total=$((total + "$1"))
  shift
done

または、forループを使用します:

total=0
for argument; do
  total=$((total + "$argument"))
done
3
AlexP

他の回答が使用したように$(())に加えて、(())を使用して、次のように内部で+=を使用することもできます。

sum=0
for x; do
  (( sum += x ))
done
echo $sum

また、提供したコードで何をしていたかを説明するのにも役立つ場合があります。基本的に、各引数を空白で分割し($@for i in $@を二重引用符で囲まなかったため)、結果をループしました。次に、行った割り当てを無視し、空白の引数をさらに2回分割し、最初のセットの最後の引数と2番目のセットの最初の引数を+で結合し、最初の引数で指定されたコマンドを残りの引数としての引数。したがって、たとえば、このスクリプトの名前がsumで、次のように呼び出した場合:sum "1 2" 3、その$@+$@は次のようにコマンド1を呼び出そうとします(/bin/1を探していても):1 "2" "3+1" "2" "3"。おそらく、bash: 1: command not foundのようなbash警告が3回(引数ごとに1回)発生する可能性があります。次に、ループ内にechoを記述したため、引数ごとに合計を1回報告しようとします。実際には、文字列のバッククォートのために、1 "2" "3"がコマンドとして再度解釈された状態で1を実行しようとします。これにより、コマンドが見つからなかったというbash警告も発生します。コマンドがなかったため、出力はなく、echoは「合計は」とエコーします。したがって、完全な結果は次のとおりです。

$ sum "1 2" 3
bash: 1: command not found
bash: 1: command not found
the total is 
bash: 1: command not found
bash: 1: command not found
the total is 
bash: 1: command not found
bash: 1: command not found
the total is 
2
JoL
#!/bin/sh

IFS='+'
printf '%s\n' "$*" | bc

テスト

$ ./script.sh 1 2 3 -1 30 0.1
35.1

"$*"は、IFSシェル変数の最初の文字で区切られた位置パラメーター(コマンドライン引数)に展開されます。 IFSをプラス記号に設定し、評価のために文字列をbcに渡します。

整数演算のみが必要な場合:

#!/bin/sh

IFS='+'
printf '%d\n' "$(( $* ))"
1
Kusalananda