[[]]テストで二重引用符を使用する理由


23

bashスクリプトに2つの整数があるとします。

value1=5
value2=3

次に、テストの場合に二重引用符を使用する必要があるのはなぜですか?例えば:

if [[ "$value1" -eq "$value2" ]]

なぜ次のものを使用しないのですか?

if [[ $value1 -eq $value2 ]]

私にとって、二重引用符は意味をなさない。


5
(データ型のように)文字列とはほとんどを持っているそれは、単語の分割を行うからシェルを防ぐことについては本当にのシェルに引用(および拡張の他の種類を。)
filbranden

13
ひどく指摘したように、この特定のコンストラクトで変数を引用する必要はありません(もちろん、どこでも1ワードの値で)、変数常に引用するようアドバイスします。コンテキストでは、変数を引用符で囲まずに残すことができることを本当に知っていますか?5and 3で必要でなくても、引用する理由は保守性です。値は後で変更される場合があり、結果のエラーは明らかではない場合があります。
ピーター-モニカの復職

2
@sudodusこれは[[ ]]、にのみ当てはまるとは思いません[ ]
ベンジャミンW.

1
あなたは正しい、@ BenjaminW。変数に二重引用符を使用することをお勧めするのは、単語の分割だけではありません。変数が空白の場合もあります。これにより、[]内のステートメントが失敗します(たとえば、[2 -eq]でエラーが発生しますが、[[]]は脆弱ではありません(単語分割の場合のように)。)
sudodus

2
@ marcelm、Bash、ksh、Zshには整数変数があり、その中[[ ]]でオペランド-eqを整数に強制します。
イルカチュウ

回答:


7

単語分割。

この例は非常にありそうにありませんが、可能があるため、防御的にコーディングする場合は、引用符でトラックをカバーしてください。

$ set -x
$ value1=5
+ value1=5
$ value2=3
+ value2=3
$ [ $value1 -eq $value2 ]
+ '[' 5 -eq 3 ']'

OK、これまでのところすべて良い。歯車にギアを投げましょう:

$ IFS=456
+ IFS=456
$ [ $value1 -eq $value2 ]
+ '[' '' -eq 3 ']'
bash: [: : integer expression expected

おっとっと。

$ [ "$value1" -eq "$value2" ]
+ '[' 5 -eq 3 ']'

ああ。


2
しかし、OPは二重括弧を使用するため、単語の分割は行われません。
user000001

5
はい、これはbashの[[ ]]構造にはあまり関係ありません。
テルドン

1
え?[ $value1 -eq $value2 ]空の場合value1は、左側に'[' -eq 3 ']'noが表示さ''れます。
チャールズダフィー

私も驚きましたが、証拠があります。
グレンジャックマン

1
この答えは質問に直接関係しません。受け入れられて驚いた。コミュニティWikiとして設定。
グレンジャックマン

35

ここで引用符は実際には必要ありません。これは、引用符で囲まれていない変数を使用しても安全な数少ないケースの1つです。これを確認するにはset -x

$ var1=""
$ var2="3"
$ set -x
$ if [[ $var1 -eq $var2 ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!
$ if [[ "$var1" -eq "$var2" ]]; then echo "match!"; else echo "no match!"; fi
+ [[ '' -eq 3 ]]
+ echo 'no match!'
no match!

上記でわかるように、テストの引用バージョンと非引用バージョンは、bashによってまったく同じものに解決されます。同じことが当てはまるはずです。zshまた、[[ ]]オペレーターです。

これはよりポータブルな場合には当てはまらないことに注意してください[ ]

$ if [ $var1 -eq $var2 ]; then echo "match!"; else echo "no match!"; fi
+ '[' -eq 3 ']'
sh: [: -eq: unary operator expected
+ echo 'no match!'
no match!

[ ]コンストラクトは、とは違って[[ ]]1、引用が必要です。


引用が必要な時期と理由について詳しく知るための便利なリンク:


この場合、整数変数を使用して、そのように宣言する方が適切です。declare -i var1=0評価されたとき。
フレディ

4
これ-eq算術比較であるため、$out(in [[ .. ]])を省いて、と書くこともできます[[ a -eq b ]]。文字列比較では$、もちろんが必要です。そのため[[ $a = $b ]]
ilkkachu

2
@ user000001良い点。もちろん、それはあなたがいることを非常に可能性があります、が欲しいものを拡大しました。たとえば、これは一致すると予想されますvar1="afoob"; var2="a*b"; [[ $var1 = $var2 ]] && echo match。グロブコンテキスト(など[[ ]])でグロブとして機能せずにグロブ文字を使用する場合は、はい、引用する必要があります。
テルドン

3
@ilkkachu、驚きました。「裸の」変数は、配列の添字または((...))or 内でのみ考慮されると考えました$((...)。動作しているように見えますが、(古い不機嫌そうな人、有効にしてください)私はそれが好きではありません。
グレンジャックマン

1
@glennjackman、それを教えてくれて申し訳ありませんが、ええ、-eq内部のオペランドと友人[[ ]]も算術コンテキストです。:)(関連:bash [[]]コマンド内の自動変数展開
ilkkachu

17

二重引用符は不要ですが、使用する理由は次のとおりです。

  • 良い習慣/習慣:この場合、それらは必要ありませんが、一般に二重引用符意図しない単語の分割を避けるためです。
  • ためvalue1value2可変であり、そしてあなたは、彼らが含まれているのか分からないかもしれません。そうでなければ、「なぜチェックするのではなく変数に悩まされるのif [[ 5 -eq 3 ]]か、それともさらに進んで、なぜif5が3に等しくないことを既に知っているのになぜ悩まされるのか?多くの場合、防御的であるほうがよい。その単語分割はで発生しませんが[[、単語分割が発生しないケースはまれです。再び、最初のポイントを参照してください。

1

あなたの質問とは直接関係ありませんが、私は

if(($ value1 == $ value2)); それから

数値を比較するとき、引用符を使用する必要はありません。


2
if (( value1 == value2 )); then。算術コンテキストでは、さえ必要ありません$。ただし、この質問は、[[ ... ]]テスト内で使用される変数に焦点を当てているようです。
クサラナンダ

1
知っている。しかし、変数名に一貫性を持たせ、常に接頭辞として$を使用するため、率直に言ってこの機能は使用しません。
framp

1

あなたは、絶対に正しい!

少なくともこの場合、二重角括弧内の引用は意味がありません。

しかし、私は毎日二重引用符を使用しているので、特に単一の角括弧式、関数やスクリプトへの引数の受け渡し、変数の割り当て(場合によっては単純なデルカレーションにはまったく役に立たない)に使用しているため、変数拡張の周りに本能的に二重引用符を書きます

二重引用符を使用すると、節約感が得られます。二重引用符があるところに帰ってくるようなものです。-D.クンマー

二重引用符を結果として包括的に実行することの利点は、それが理にかなっている場合に限り、bashを初めて使用する同僚がより安定したスクリプトを作成する方法を学習できることです。また、bashを使用したデータ処理の技術は、データストリーム(変数を含む)をフィールドセパレーターで分離し、それらをフィルターにパイプすることに関するものであることも強調しています。データチャンクをストリームから分離したらすぐに、二重引用符でまとめます!

もう1つの利点は、コードハイライトエディター内で二重引用符で囲まれた文字列を含むbashスクリプトの読みやすさです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.