bashの二重角括弧と単一角括弧の違いは何ですか?


426

私はちょうど何の違いを疑問に思いました

[[ $STRING != foo ]]

そして

[ $STRING != foo ]

それとは別に、後者はposix準拠であり、shにあり、前者はbashにある拡張機能です。


1
また、ifステートメントのコンテキストなどで、括弧をまったく使用しないことを考えて
Kev

また、Ubuntuのドキュメントから:wiki.ubuntu.com/...
radistao

回答:


309

いくつかの違いがあります。私の意見では、最も重要なものは次のとおりです。

  1. [Bashやその他の多くの最新のシェルに組み込まれています。組み込み[test、終了の追加要件と似ています]。組み込みコマンド[とは、test機能を模倣/bin/[し、/bin/testその限界と一緒にスクリプトが下位互換性になるように。元の実行可能ファイルは、主にPOSIX準拠と後方互換性のためにまだ存在しています。type [Bashでコマンドを実行すると[、デフォルトで組み込みとして解釈されます。(注:PATHwhich [で実行可能ファイルのみを検索し、に相当します)type -p [
  2. [[互換性がそれほど高くないため、どのような/bin/shポイントでも機能するとは限りません。だから、[[より近代的なバッシュ/ Zshの/のkshオプションがあります。
  3. ので[[、シェルに組み込まれており、従来の要件を持っていない、あなたはに基づいて単語の分割を心配する必要はありませんIFSのスペースを文字列に評価された変数に台無しに変数。したがって、変数を二重引用符で囲む必要はありません。

ほとんどの場合、残りはより優れた構文です。より多くの違いを見るには、FAQの回答へのこのリンクをお勧めします:testと[と[[の違いは何ですか?。実際、bashスクリプトについて真剣に考えているのであれば、FAQ、Pitfalls、およびGuide を含むwiki全体を読むことをお勧めしますガイドセクションのテストセクションでも、これらの違いについて説明します。また、移植性を心配する必要がない場合、作成者がより良い選択であると考える理由についても説明します。主な理由は次のとおりです。[[

  1. 実際に変数として読み取られるように、テストの左側を引用符で囲むことを心配する必要はありません。
  2. あなたはより少ないとより大きくエスケープする必要はありません< >入力のリダイレクト、ファイルを上書きすることによってすることができます本当に混乱いくつかのものをアップとして評価を取得していない彼らのために順番にバックスラッシュとします。これもビルトインに戻り[[ます。[(テスト)が外部プログラムである場合、シェルは、それが評価された方法で例外を作成しなければならないであろう<>する場合にのみ/bin/test、本当に意味を成さないであろう、と呼ばれています。

5
おかげで、bash FAQへのリンクは私が探していたものでした(そのページについては知りませんでした、ありがとう)。
-0x89

2
この情報を使用して投稿を編集しましたが、[とtestはビルトインとして実行されます。ビルトインは/ bin / [と/ bin / testを置き換えるように設計されましたが、バイナリの制限も再現する必要がありました。コマンド 'type ['は、組み込みが使用されていることを確認します。「これは[」だけPATH上の実行可能ファイルを検索し、「と等価でタイプ-P [」
klynch

133

要するに:

[はbash Builtinです

[[]]はbash キーワードです

キーワード:キーワードはビルトインによく似ていますが、主な違いは特別な解析ルールがキーワードに適用されることです。たとえば、[はbashビルトインで、[[はbashキーワードです。どちらもテスト用に使用されますが、[[は組み込みではなくキーワードであるため、いくつかの特別な解析ルールの恩恵を受けます。

  $ [ a < b ]
 -bash: b: No such file or directory
  $ [[ a < b ]]

最初の例は、bashがファイルbをコマンド[a]にリダイレクトしようとするため、エラーを返します。2番目の例は、実際にあなたが期待することを行います。文字<には、ファイルリダイレクト演算子の特別な意味はなくなりました。

ソース:http : //mywiki.wooledge.org/BashGuide/CommandsAndArguments


3
[POSIXシェルコマンドです。組み込みの必要はありません。]構文はバランスが取れるように、そのコマンドが探す引数にすぎません 。このコマンドは、終了を検索しないtestことを除いて、同義語です。test]
カズ


81

行動の違い

Bash 4.3.11のいくつかの違い:

  • POSIX対Bash拡張機能:

  • 通常コマンドvsマジック

    • [ 奇妙な名前の通常のコマンドです。

      ]は単なる引数であり[、それ以上の引数が使用されないようにします。

      Ubuntu 16.04には実際には/usr/bin/[coreutilsが提供する実行可能ファイルがありますが、bashの組み込みバージョンが優先されます。

      Bashがコマンドを解析する方法に変更はありません。

      特に、<リダイレクトで&&あり、||複数のコマンドを連結( )\、でエスケープされない限りサブシェルを生成し、単語の展開は通常どおり行われます。

    • [[ X ]]X魔法のように解析される単一の構成体です。<&&||および()特別に処理し、単語分割ルールは異なるされています。

      また、などの違いも=あり=~ます。

      Basheseの場合:[は組み込みコマンドであり[[、キーワードです:https : //askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword

  • <

  • && そして ||

    • [[ a = a && b = b ]]:真、論理
    • [ a = a && b = b ]:構文エラー、&&ANDコマンド区切りとして解析cmd1 && cmd2
    • [ a = a -a b = b ]:同等ですが、POSIX³で非推奨
    • [ a = a ] && [ b = b ]:POSIXおよび信頼できる同等物
  • (

    • [[ (a = a || a = b) && a = b ]]:偽
    • [ ( a = a ) ]:構文エラー、()サブシェルとして解釈されます
    • [ \( a = a -o a = b \) -a a = b ]:同等()ですが、POSIXでは非推奨です
    • { [ a = a ] || [ a = b ]; } && [ a = b ]POSIXで同等の5
  • 単語分割と展開時のファイル名生成(split + glob)

    • x='a b'; [[ $x = 'a b' ]]:true、引用符は不要
    • x='a b'; [ $x = 'a b' ]:構文エラー、展開先 [ a b = 'a b' ]
    • x='*'; [ $x = 'a b' ]:現在のディレクトリに複数のファイルがある場合の構文エラー。
    • x='a b'; [ "$x" = 'a b' ]:POSIXと同等
  • =

    • [[ ab = a? ]]:true 。パターンマッチングを行うためです(* ? [魔法です)。現在のディレクトリ内のファイルに展開しません。
    • [ ab = a? ]a?globが展開します。したがって、現在のディレクトリ内のファイルに応じて、trueまたはfalseになります。
    • [ ab = a\? ]:glob展開ではなくfalse
    • =そして==、両方で同じである[[[、しかし==バッシュの拡張機能です。
    • case ab in (a?) echo match; esac:POSIXと同等
    • [[ ab =~ 'ab?' ]]:false 4、魔法を失う''
    • [[ ab? =~ 'ab?' ]]:true
  • =~

    • [[ ab =~ ab? ]]:true、POSIX 拡張正規表現一致、?glob展開しない
    • [ a =~ a ]: 構文エラー。同等のbashはありません。
    • printf 'ab\n' | grep -Eq 'ab?':POSIX同等(単一行データのみ)
    • awk 'BEGIN{exit !(ARGV[1] ~ ARGV[2])}' ab 'ab?':POSIXと同等。

推奨事項:常に使用します[]

[[ ]]私が見たすべての構成体にPOSIXに相当するものがあります。

あなたを使用する[[ ]]場合:

  • 移植性を失う
  • 読者に別のbash拡張機能の複雑さを学習させる。[は、奇妙な名前を持つ通常のコマンドであり、特別なセマンティクスは含まれていません。

[[...]]¹Kornシェルの同等のコンストラクトに触発された

²が、aor b+orなどindex)の一部の値では失敗し、10進整数の場合は数値比較をa行いbます。expr "x$a" '<' "x$b"両方で動作します。

³ものいくつかの値のために失敗したabのような!、または(

bash 3.2以降の4および提供されているbash 3.1との互換性は有効ではありません(などBASH_COMPAT=3.1

5(とここでグルーピングものの{...;}代わりにコマンド群(...)として不要サブシェルを実行することになる)が必要でない||&&(とは対照的に、シェル演算子||及び&& [[...]]オペレータ又は-o/ -a [オペレータ)は等しい優先順位を有します。だから[ a = a ] || [ a = b ] && [ a = b ]同等になります。


printf 'ab' | grep -Eq 'ab?'内で使用するにはif [ … ]
meeDamian

1
@meeDamian if ( printf 'ab' | grep -Eq 'a' ); then echo 'a'; fi[]はのようなコマンドgrepです。()そのコマンドには必要ないかもしれませんが、よく|わかりません:のために追加したのは、Bashが物事をどのように解析するかに依存します。なかった場合は、|ちょうどあなたが書くことができると確信していますif cmd arg arg; then
Ciro Santilli新疆改造中心法轮功六四事件


1
素敵なリスト!参照:wiki.ubuntu.com/...は
radistao

5

シングルブラケットすなわち[]、条件式を囲んでに準拠POSIXシェルです。

二重括弧つまり[[]]、これはbashのや他のシェル(zshの、kshの)によってサポートされている標準のPOSIXバージョンの強化(または拡張)バージョンです。

bashのでは、我々が使用する数値比較のためにeqneltおよびgt比較のために二重括弧で、我々は使用することができ==!=<,そして>文字通り。

  • [testコマンドの同義語です。シェルに組み込まれている場合でも、新しいプロセスを作成します。
  • [[ これは新しい改良バージョンであり、プログラムではなくキーワードです。

例えば:

[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory 
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works

4

マンページの関連セクションをすばやく読むと、主な違いは、==and !=演算子がリテラル文字列ではなくパターンと一致することと、=~正規表現比較演算子があることです。

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