個別に連携する2つのスクリプトがありますが、一緒に機能させる方法がわかりません。
使命は、bashスクリプトが演算子と整数のリストを受け入れ、コマンドにアクションを実行させることです。
デフォルトではスクリプトを使用できる必要があります。
test.sh add 1 2 3
5
test.sh sub 4 2 1
1
私の最初のスクリプトは
for var in $@
do
sum=$(( sum + var ))
done
echo $sum
2番目のスクリプトは
if [ $operator = add ]; then
add= echo $(($a+$b))
elif
答え1
スクリプトは、最初のコマンドライン引数を別の変数として選択し、コマンドライン引数のリストからop
削除します。
#!/bin/sh
op=$1
shift
このスクリプトをadd 1 2 3
引数として使用すると、コードは文字列add
をに割り当ててop
保持します。1 2 3
"$@"
その後、残りのコマンドライン引数を繰り返すことができます。
#!/bin/sh
op=$1
shift
for arg do
# some commands should go here
done
追加されたループは、変数が残りのarg
各コマンドライン引数の値を順番に取るようにします。このようにループの先頭を作成することもできますが、for arg in "$@"; do ...
より多くの入力が必要になり、プログラマは時々引用符を追加することを忘れます$@
。
値によっては、$op
ループ内で複数のアクションのいずれかが発生する可能性があります。私たちは$op
それが何であるかを確認し、正しいことをするために簡単なテストをすることができます。いずれにしても、下にいくつかの値が累積され、acc
そのacc
値は(質問にコマンドが表示される方法に応じて)最初の数字で初期化され、その数字もパラメータリストから削除する必要があります。
#!/bin/sh
op=$1
shift
acc=$1
shift
for arg do
case $op in
add) acc=$(( acc + arg )) ;;
sub) acc=$(( acc - arg )) ;;
mul) acc=$(( acc * arg )) ;;
div) acc=$(( acc / arg )) ;; # note: integer division here
*)
printf 'Unknown operation: %s\n' "$op" >&2
exit 1
esac
done
printf '%s\n' "$acc"
スクリプトを保存し、実行可能にしてテストします。
$ ./script add 1 2 3
6
$ ./script sub 4 2 1
1
$ ./script xor a b c
Unknown operation: xor
$ ./script add
script[7]: shift: nothing to shift
最後の2回の呼び出しに注意してください。最後は数字を提供しないので、2番目はshift
失敗します。 2番目の呼び出しは、ジョブが不明であることを知らせ、早期に終了します。
op
割り当てと初期化を少し変更すると、acc
エラーメッセージをより便利にすることができます。
#!/bin/sh
op=${1:?Expected operator}
shift
acc=${1:?Expected number}
shift
for arg do
case $op in
add) acc=$(( acc + arg )) ;;
sub) acc=$(( acc - arg )) ;;
mul) acc=$(( acc * arg )) ;;
div) acc=$(( acc / arg )) ;; # note: integer division here
*)
printf 'Unknown operation: %s\n' "$op" >&2
exit 1
esac
done
printf '%s\n' "$acc"
もう一度テストしてください:
$ ./script
script[3]: 1: Expected operator
$ ./script add
script[6]: 1: Expected number
$ ./script add 1 2
3
これらのエラーメッセージの正確な形式は、システム内のシェルの役割によって異なります/bin/sh
。
答え2
最初のスクリプトは繰り返されます$@
。オペランドを追加するには、最初のパラメータ(op=$1
)を保存してからを使用しますshift
。
からman bash
:
シフト[n]
n+1 ...の位置パラメータ名が$ 1 ...に変更されました。 $#から$#-n+1までの数値で表されるパラメータは設定されません。 n は、$# 以下の負以外の数字でなければなりません。 nが0の場合、パラメータは変更されません。 n を指定しない場合、1 とみなされます。 nが$#より大きい場合、位置パラメータは変更されません。 n が $# より大きいか 0 より小さい場合、戻り状態は 0 より大きく、それ以外の場合は 0 です。
$result
最初の引数で初期化してからshift
もう一度使用してください。
また、$@
ループを実行するときは必ず引用符を使用してください(読むここ)。
#!/bin/bash
op=$1
shift
result=$1
shift
for var in "$@"; do
result=$(( result $op var ))
done
echo "$result"
shift
ワンステップで行うこともできます。
op=$1
result=$2
shift 2
走っtest.sh + 1 2 3
たり test.sh '*' 1 2 3
…
('*'
ファイル名に拡張されないように引用符で囲む必要があります。)
しかし、私はループの代わりにbc
andを使いたいです。$IFS
$(( ... )))
#!/bin/bash
OLDIFS="$IFS"
IFS=$1
shift
bc <<< "scale=5; $*"
IFS=$OLDIFS
"$*"
単一の単語に展開します"$1c$2c..."
。これは通常c
空白ですが、実際にはの最初の文字なので、必要に応じてIFS
指定できます。