web-dev-qa-db-ja.com

二項演算子が必要です-シェルスクリプト引数の引用質問

シェルスクリプトを実行するときに引数を追加する方法について質問があります。

IP範囲をブロックするのに役立つ簡単なスクリプトがあります。

〜/ block_ip.sh:

if [ ! $3 ]
then
 echo "usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'"
 exit 1
fi

echo "adding $3"
Sudo iptables -I INPUT -s $2 -j $1 -m comment --comment "$3"

引数なしでこれを実行すると、出力は期待どおりです:

~$ ./block_ip.sh
usage ~/block_ip.sh (DROP/ACCEPT) '0.0.0.0' 'amsterdam'

ただし、スペースが"binary operator expected"の予期しない出力の原因であると思われます。

~$ ./block_ip.sh DROP '1.0.0.0/8' 'south brisbane qld'
./block_ip.sh: line 1: [: brisbane: binary operator expected
adding south brisbane au

しかし、それは予期しない出力にもかかわらずそれを追加します:

Chain INPUT (policy ACCEPT)
num  target     prot opt source           destination
1    DROP       all  --  1.0.0.0/8        anywhere         /* south brisbane au */

これが引用の問題である場合、(スペースをエスケープするためにバックスラッシュを使用せずに)引数をどのように形成しますか?もちろん、私はスクリプトに変更を加える必要があると思います。これも許容できる解決策です。

2
WEBjuju

うん、それは引用問題です:[ ! $3 ][ ! south brisbane qld ][]の間の4つの引数)に展開されます。そして、最初の引数が!である4つの引数が見つかると、[[ ! arg1 op arg2 ]のようなものを期待します。ここで、opは2項演算子です。 (これも、[ .. ][[ .. ]]の違いの1つです。 このQを参照 および このQも です)

brisbaneは有効な演算子ではないため、不平を言って2を返します。これは不正なため、if内のステートメントは実行されません。エラーと通常の失敗したテストの違いを確認するには、戻り値を2に対して明示的にテストする必要があります。

一方、$3が空の場合、テストは[ ! ]になります。これは、唯一の引数が空でないかどうかを確認する1つの引数のテストです(つまり、1文字の文字列!です)。その場合、それは意図したとおりに機能しますが、おそらく予期した理由ではありません。


[ ! "$3" ]または[ -z "$3" ]が文字列を[の1つの引数として保持するようにします。

もちろん、テストの意味を逆にしてif内で実際の作業を行うこともできます。これにより、テストでエラーが発生しても、メインコマンドが実行されなくなります。しかし、それはコード構造をもう少し不明確にするでしょう。

7
ilkkachu