どういう違いがあるのか
[[ $STRING != foo ]]
そして
[ $STRING != foo ]
つまり、後者はposix準拠であり、shにあり、前者はbashにある拡張機能です。
いくつかの違いがあります。私の意見では、最も重要なもののいくつかは次のとおりです。
[
は、Bashおよび他の多くの最新のシェルに組み込まれています。組み込みの[
はtest
に似ていますが、クロージング]
の追加要件があります。ビルトイン[
とtest
は、機能の/bin/[
と/bin/test
とその制限を模倣しているため、スクリプトに下位互換性があります。元の実行可能ファイルは、主にPOSIX準拠と下位互換性のためにまだ存在しています。 Bashでtype [
コマンドを実行すると、[
がデフォルトで組み込みとして解釈されます。 (注:which [
は[〜#〜] path [〜#〜]で実行可能ファイルのみを検索し、type -p [
と同等です)[[
はそれほど互換性がなく、/bin/sh
が指しているものとは必ずしも連携しません。したがって、[[
はよりモダンなBash/Zsh/Kshオプションです。[[
はシェルに組み込まれており、レガシー要件がないため、[〜#〜] ifs [〜#〜]変数に基づくWordの分割について心配する必要はありませんスペースを含む文字列に評価される変数を台無しにする。したがって、実際に変数を二重引用符で囲む必要はありません。ほとんどの場合、残りはより良い構文です。より多くの違いを見るために、私はこのリンクをFAQ答え: テスト、[と[[? の違いは何ですか。 bashスクリプトについては、FAQ、 落とし穴 、およびガイドを含む wiki 全体をお読みになることをお勧めします ガイドセクションのテストセクション は、これらについて説明していますまた、移植性について心配する必要がない場合は、著者が[[
の方が適していると考える理由も主な理由は次のとおりです。
< >
を超えてエスケープする必要はありません。ファイルを上書きすることで、実際に混乱を招く可能性があります。これは、組み込みの[[
に戻ります。 [(test)が外部プログラムの場合、<
が呼び出されている場合にのみ、シェルは>
および/bin/test
を評価する方法で例外を作成する必要があります。センス。要するに:
[は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
動作の違い
Bash 4.3.11のいくつかの違い:
POSIX対Bash拡張:
[
_ is POSIX[[
_はBashの拡張機能です。ドキュメントは https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructs に記載されています。通常のコマンド対魔法
_[
_は、奇妙な名前を持つ通常のコマンドです。
_]
_は_[
_の単なる引数であり、これ以上の引数が使用されないようにします。
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 < b ]]
_:辞書式比較[ a \< b ]
_:上記と同じ。 _\
_必須、または他のコマンドと同様にリダイレクトを行います。バッシュ拡張。expr a \< b > /dev/null
_:POSIX相当²、以下を参照: https://stackoverflow.com/questions/21294867/how-to-test-strings-for-lexicographic-less-than-or-equal-in-bash/52707989#52707989_&&
_および_||
_
[[ 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があります。
_[[ ]]
_を使用する場合:
[
_は、奇妙な名前の通常のコマンドであり、特別なセマンティクスは関与していません。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では、数値比較にeq
、ne
、lt
およびgt
を使用します。比較には二重括弧を使用して==
、!=
、<,
および>
文字通り。
[
はテストコマンドの同義語です。シェルに組み込まれていても、新しいプロセスを作成します。[[
は、その改良版であり、プログラムではなくキーワードです。例えば:
[ var1 lt var2] #works
[ var1 < var2] #error: var2 No such file or directory
[ var1 \< var2] #works with escape
[[ var1 < var2]] #works
マンページの関連セクションをすばやく読むと、主な違いは==
および!=
演算子は、リテラル文字列ではなくパターンと照合します。また、=~
正規表現比較演算子。