800

同僚が最近のコード レビューで、この構造は次のような構造[[ ]]よりも優先されると主張しました。[ ]

if [ "`id -nu`" = "$someuser" ] ; then
     echo "I love you madly, $someuser"
fi

彼は根拠を示すことができませんでした。ありますか?

4

9 に答える 9

792

[[驚きが少なく、一般的に安全に使用できます。しかし、それは移植可能ではありません - POSIX はそれが何をするかを指定しておらず、一部のシェルのみがそれをサポートしています (bash のほかに、ksh もそれをサポートしていると聞きました)。たとえば、次のことができます。

[[ -e $b ]]

ファイルが存在するかどうかをテストします。しかし、[では、 を引用する必要があります$b。これは、引数を分割し、"a*"(where[[は文字通りに取る) のようなものを展開するためです。これは[、外部プログラムになり、他のすべてのプログラムと同じようにその引数を受け取る方法にも関係しています (ただし、組み込みプログラムにすることもできますが、それでもこの特別な処理はありません)。

[[=~C ライクな言語で知られているような演算子との正規表現マッチングなど、他にもいくつかの優れた機能があります。ここにそれについての良いページがあります: testの違いは何ですか? [[[およびBash テスト

于 2009-03-21T15:44:09.887 に答える
320

動作の違い

Bash 4.3.11 でのいくつかの違い:

  • POSIX vs Bash 拡張機能:

  • 通常のコマンドと魔法

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

      ]の最後の引数です[

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

      Bash がコマンドを解析する方法は何も変更されません。

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

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

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

    Bashese の場合:[は組み込みコマンドであり[[、キーワードです: shell builtin と shell キーワードの違いは何ですか?

  • <

    • [[ a < b ]]: 辞書式比較
    • [ a \< b ]: 同上。\必要な場合、または他のコマンドと同様にリダイレクトを行います。バッシュ拡張。
    • expr x"$x" \< x"$y" > /dev/nullまたは[ "$(expr x"$x" \< x"$y")" = 1 ]: POSIX に相当するもの。参照: Bash で辞書式以下の文字列をテストする方法は?
  • &&||

    • [[ a = a && b = b ]]: 真、論理的、および
    • [ a = a && b = b ]: 構文エラー、&&AND コマンド区切りとして解析されましたcmd1 && cmd2
    • [ a = a ] && [ b = b ]: POSIX の信頼できる同等のもの
    • [ a = a -a b = b ]: ほぼ同等ですが、論理演算として解釈されるaor blike!またはの一部の値に対して正気ではなく、失敗するため、POSIX では推奨されていません。(
  • (

    • [[ (a = a || a = b) && a = b ]]: 間違い。よりも優先順位が高いため、それがなけれ( )ば true になります。[[ && ]][[ || ]]
    • [ ( a = a ) ]: 構文エラー、()サブシェルとして解釈されます
    • [ \( a = a -o a = b \) -a a = b ]: 同等ですが()、 、-a、および-oは POSIX で非推奨です。よりも優先順位が高いため、それがなけれ\( \)ば true になります。-a-o
    • { [ a = a ] || [ a = b ]; } && [ a = b ]非推奨ではない POSIX の同等物。ただし、この特定のケースでは、 と シェル演算子は and とは異なり同等の優先順位を持っているため、単に :と書くこともでき[ a = a ] || [ a = b ] && [ a = b ]ました。||&&[[ || ]][[ && ]]-o-a[
  • 展開時の単語分割とファイル名の生成 (分割 + グロブ)

    • x='a b'; [[ $x = 'a b' ]]: 真実。引用符は必要ありません
    • 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、グロブ展開ではない
    • ===は と の両方[で同じです[[==、Bash 拡張機能です。
    • case ab in (a?) echo match; esac: POSIX 相当
    • [[ ab =~ 'ab?' ]]: false、''Bash 3.2 以降では魔法を失い、Bash 3.1 への提供された互換性は有効になっていません (のようにBASH_COMPAT=3.1)
    • [[ ab? =~ 'ab?' ]]: 真実
  • =~

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

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

[[ ]]私が見たすべてのコンストラクトには、POSIX に相当するものがあります。

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

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

重要な修正と追加をしてくれたStéphane Chazelasに感謝します。

于 2017-11-30T15:04:25.730 に答える
66

[[ ]]にはより多くの機能があります - 詳細についてはAdvanced Bash Scripting Guideを参照することをお勧めします。具体的にはChapter 7. Testsの拡張テスト コマンドセクションです。

ちなみに、ガイドノートにあるように[[ ]]、ksh88 ( KornShellの 1988 年版) で導入されました。

于 2009-03-21T15:32:50.133 に答える
19

テスト、ブラケット、またはダブルブラケットのどのコンパレーターが最速ですか? :

二重括弧は「複合コマンド」であり、as test と単一括弧はシェルの組み込みコマンドです (実際には同じコマンドです)。したがって、一重括弧と二重括弧は異なるコードを実行します。

テストと単一ブラケットは、独立した外部コマンドとして存在するため、最も移植性があります。ただし、リモートで最新バージョンの BASH を使用している場合は、二重ブラケットがサポートされます。

于 2009-03-21T15:34:15.340 に答える
-1

[[ ]] 二重括弧は、SunOSの特定のバージョンではサポートされておらず、関数宣言内では完全にサポートされていません。

GNU Bash、バージョン 2.02.0(1) リリース (sparc-sun-solaris2.6)

于 2013-03-19T14:59:51.953 に答える
-2

一言で言えば、 [[ は別のプロセスをフォークしないので優れています。別のプロセスをフォークするため、括弧なしまたは単一の括弧は二重括弧よりも遅くなります。

于 2010-11-24T16:08:48.837 に答える