web-dev-qa-db-ja.com

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

どういう違いがあるのか

[[ $STRING != foo ]]

そして

[ $STRING != foo ]

つまり、後者はposix準拠であり、shにあり、前者はbashにある拡張機能です。

451
0x89

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

  1. [は、Bashおよび他の多くの最新のシェルに組み込まれています。組み込みの[testに似ていますが、クロージング]の追加要件があります。ビルトイン[testは、機能の/bin/[/bin/testとその制限を模倣しているため、スクリプトに下位互換性があります。元の実行可能ファイルは、主にPOSIX準拠と下位互換性のためにまだ存在しています。 Bashでtype [コマンドを実行すると、[がデフォルトで組み込みとして解釈されます。 (注:which [[〜#〜] path [〜#〜]で実行可能ファイルのみを検索し、type -p [と同等です)
  2. [[はそれほど互換性がなく、/bin/shが指しているものとは必ずしも連携しません。したがって、[[はよりモダンなBash/Zsh/Kshオプションです。
  3. [[はシェルに組み込まれており、レガシー要件がないため、[〜#〜] ifs [〜#〜]変数に基づくWordの分割について心配する必要はありませんスペースを含む文字列に評価される変数を台無しにする。したがって、実際に変数を二重引用符で囲む必要はありません。

ほとんどの場合、残りはより良い構文です。より多くの違いを見るために、私はこのリンクをFAQ答え: テスト、[と[[? の違いは何ですか。 bashスクリプトについては、FAQ、 落とし穴 、およびガイドを含む wiki 全体をお読みになることをお勧めします ガイドセクションのテストセクション は、これらについて説明していますまた、移植性について心配する必要がない場合は、著者が[[の方が適していると考える理由も主な理由は次のとおりです。

  1. 実際に変数として読み取られるように、テストの左側を引用することを心配する必要はありません。
  2. 入力リダイレクトとして評価されないようにするために、バックスラッシュで< >を超えてエスケープする必要はありません。ファイルを上書きすることで、実際に混乱を招く可能性があります。これは、組み込みの[[に戻ります。 [(test)が外部プログラムの場合、<が呼び出されている場合にのみ、シェルは>および/bin/testを評価する方法で例外を作成する必要があります。センス。
325
Kyle Brandt

要するに:

[はbashですBuiltin

[[]]はbashKeywords

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

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

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

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

138
abhiomkar

動作の違い

Bash 4.3.11のいくつかの違い:

  • POSIX対Bash拡張:

  • 通常のコマンド対魔法

    • _[_は、奇妙な名前を持つ通常のコマンドです。

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

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

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

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

    • _[[ X ]]_は、Xを魔法のように解析する単一の構成要素です。 _<_、_&&_、_||_および_()_は特別に扱われ、Wordの分割規則は異なります。

      _=_と_=~_のような違いもあります。

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

  • _<_

  • _&&_および_||_

    • _[[ a = a && b = b ]]_:true、論理および
    • _[ a = a && b = b ]_:構文エラー、ANDコマンドセパレータとして解析された_&&_ _cmd1 && cmd2_
    • _[ a = a -a b = b ]_:同等ですが、POSIXでは非推奨です³
    • _[ a = a ] && [ b = b ]_:POSIXおよび信頼できる同等物
  • _(_

    • [[ (a = a || a = b) && a = b ]]:false
    • [ ( a = a ) ]:構文エラー、_()_はサブシェルとして解釈されます
    • [ \( a = a -o a = b \) -a a = b ]:同等、ただし_()_はPOSIXで非推奨
    • _{ [ a = a ] || [ a = b ]; } && [ a = b ]_同等のPOSIX5
  • 拡張時の単語分割とファイル名生成(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?_グロブが展開されます。したがって、現在のディレクトリ内のファイルに応じて、trueまたはfalseになります。
    • _[ ab = a\? ]_:false、glob拡張ではない
    • _=_と_==_は、_[_と_[[_の両方で同じですが、_==_はBash拡張機能です。
    • case ab in (a?) echo match; esac:同等のPOSIX
    • _[[ ab =~ 'ab?' ]]_:false4、_''_で魔法を失う
    • _[[ ab? =~ 'ab?' ]]_:true
  • _=~_

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

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

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

_[[ ]]_を使用する場合:

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

Ko Kornシェルの同等の_[[...]]_構成から発想を得た

²しかし、aまたはbの一部の値(_+_またはindexなど)で失敗し、aおよびbは、10進整数のように見えます。 _expr "x$a" '<' "x$b"_は両方を回避します。

³また、_!_または_(_のようなaまたはbの一部の値でも失敗します。

4 bash 3.2以降では、bash 3.1との互換性が提供されていません(_BASH_COMPAT=3.1_など)。

5 ただし、_{...;}_および_(...)_シェル演算子(反対ではない)として、グループ化(ここでは、_||_ではなく_&&_コマンドグループを使用)は不要です。 _||_および_&&_ _[[...]]_演算子または_-o_/_-a_ _[_演算子)の優先順位は同じです。したがって、_[ a = a ] || [ a = b ] && [ a = b ]_は同等です。

単一ブラケットつまり[]は、条件式を囲むためにPOSIXシェルに準拠しています。

ダブルブラケットつまり[[]]は標準POSIXバージョンの拡張(または拡張)バージョンであり、bashおよびその他のシェル(zsh、ksh)でサポートされています。

Bashでは、数値比較にeqneltおよびgtを使用します。比較には二重括弧を使用して==!=<,および>文字通り。

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

例えば:

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

マンページの関連セクションをすばやく読むと、主な違いは==および!=演算子は、リテラル文字列ではなくパターンと照合します。また、=~正規表現比較演算子。

4
womble