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

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

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" 

ただし、スペースが原因のようです。 「二項演算子が必要です」の予期しない出力:

~$ ./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 */ 

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

コメント

  • テストの目標が$3は、3つのパラメーターがあることを確認するだけです。より単純な$#シェル変数を使用できます。これは、パラメーターの数を保持します。 if [ $# -ne 3 ]

回答

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

brisbaneは有効な演算子ではないため、文句を言って2を返します。これは偽であるため、

は実行されません。エラーと通常の失敗したテストの違いを区別するには、2に対して戻り値を明示的にテストする必要があります。

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


[ ! "$3" ]またはは、文字列を[の1つの引数として保持します。

もちろん、テストの意味を逆にして、 if内で実際に動作するため、テストでエラーが発生すると、メインコマンドの実行が回避されます。ただし、コード構造が少し不明確になります。

コメント

  • いいです-それで、それが機能している理由は、エラーが発生しても、$ 3が空ではないので' !テストに合格し、iptablesコマンドで引用したので、スペースを含む拡張はすでに処理されています-そうですか?
  • そして' iptables行のパラメーターも引用したいと思います
  • @WEBjuju、ああ、そうです、それについて書くつもりで、なぜそれが機能するのかを編集しました。そしてそうです、iptablesコマンドに引用符が含まれているので、正常に機能します。
  • @ilkkachu gotcha、はい、私の側ではばかげているようです。どういうわけか私は無意識のうちにそれを知っていましたが、'実用的な解決策に知識をもたらすことができませんでした。今までこの基本的なテナントを知らずに何とか混乱してきましたが、真剣にレベルアップしました。どうもありがとう!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です