私は約bashの例を読んでif
いますが、いくつかの例は単一の角括弧で書かれています:
if [ -f $param ]
then
#...
fi
角かっこが二重になっているもの:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
違いはなんですか?
私は約bashの例を読んでif
いますが、いくつかの例は単一の角括弧で書かれています:
if [ -f $param ]
then
#...
fi
角かっこが二重になっているもの:
if [[ $? -ne 0 ]]
then
start looking for errors in yourlog
fi
違いはなんですか?
回答:
シングル[]
はposixシェル準拠の条件テストです。
Double [[]]
は標準への拡張であり、[]
bashや他のシェル(zsh、kshなど)でサポートされています。これらは追加の操作(および標準のposix操作)をサポートします。たとえば、正規表現の||
代わりに-o
と一致し=~
ます。相違点の完全なリストは、条件付き構文のbashマニュアルセクションにあります。
[]
スクリプトをシェル間で移植できるようにしたい場合はいつでも使用できます。で[[]]
サポートされ[]
ていない条件式が必要で、移植性を必要としない場合に使用します。
[[ ]]
(例:bash with #!/bin/bash
または#!/usr/bin/env bash
)、ポータブルオプションを使用する必要があることを付け加えます。/ bin / shがこのような拡張機能をサポートすることを前提とするスクリプトは、最近のDebianやUbuntuのリリースのようなOSでは機能しません。
行動の違い
Bash 4.3.11でテスト済み:
POSIX vs Bash拡張:
[
POSIX[[
https://www.gnu.org/software/bash/manual/bash.html#Conditional-Constructsに記載されているBash拡張機能です。通常のコマンド対魔法
[
変な名前の通常のコマンドです。
]
[
それ以上の引数が使用されないようにするための単なる引数です。
Ubuntu 16.04には、実際には/usr/bin/[
coreutilsによって提供される実行可能ファイルがありますが、bash組み込みバージョンが優先されます。
Bashがコマンドを解析する方法に変更はありません。
特に、<
はリダイレクトされ、複数のコマンド&&
を||
連結し、( )
によってエスケープされない限りサブシェルを生成し\
、通常どおりに単語の展開が行われます。
[[ X ]]
X
魔法のように解析される単一の構造です。<
、&&
、||
および()
特別に処理し、単語分割ルールは異なるされています。
=
やなどの違いもあり=~
ます。
バシェス語で[
は:は組み込みコマンドであり[[
、キーワードです:https : //askubuntu.com/questions/445749/whats-the-difference-between-shell-builtin-and-shell-keyword
<
[[ a < b ]]
:辞書式比較[ a \< b ]
: 同上。\
必須、または他のコマンドと同様にリダイレクトを行います。バッシュ拡張。expr a \< b > /dev/null
:POSIX相当²、参照:Bashで辞書式以下の文字列をテストする方法?&&
そして ||
[[ 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 ]
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?
グロブが拡張されます。したがって、現在のディレクトリ内のファイルに応じて、trueまたはfalseになります。[ ab = a\? ]
:false、グロブ拡張ではない=
そして==
、両方で同じである[
と[[
、しかし==
バッシュの拡張機能です。case ab in (a?) echo match; esac
:POSIX相当[[ ab =~ 'ab?' ]]
:false 4、魔法を失う''
[[ 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
小数、整数のような表情を。expr "x$a" '<' "x$b"
両方を回避します。
³ものいくつかの値のために失敗したa
かb
のような!
、または(
。
bash 3.2以降では4で、bash 3.1との互換性はありません(などBASH_COMPAT=3.1
)。
5(およびand 演算子または/ 演算子とは対照的に)およびシェル演算子の優先順位が等しいため、グループ化(ここでは、{...;}
代わりにコマンドグループを使用し(...)
て不要なサブシェルを実行します)は必要ありません。したがって同等です。||
&&
||
&&
[[...]]
-o
-a
[
[ a = a ] || [ a = b ] && [ a = b ]
[]
することを私の好みとして読む必要があります:[]
移植性を失わないようにする場合に使用します。述べたように、ここで:POSIXまたはBourneShellへの移植性/適合性が懸念される場合は、古い構文を使用する必要があります。一方、スクリプトでBASH、Zsh、またはKornShellが必要な場合、新しい構文は通常より柔軟ですが、必ずしも下位互換性があるとは限りません。私はむしろ一緒に行きたい[[ ab =~ ab? ]]
私ができる場合と比べて、下位互換性の心配がありませんprintf 'ab' | grep -Eq 'ab?'
条件テスト([...])の単一の括弧内で=
は、singleなどの一部の演算子がすべてのシェルで==
サポートされていますが、古いシェルの一部では演算子の使用がサポートされていません。
条件テスト(つまり、[[...]])のための二重括弧内には、使用して差がない=
か、==
古いか新しいシェルでは。
編集:次の点にも注意してください:bashでは、可能な場合は常にダブルブラケット[[...]]を使用してください。シングルブラケットよりも安全だからです。その理由を次の例で説明します。
if [ $var == "hello" ]; then
$ varがnullまたは空の場合、スクリプトは次のように表示します。
if [ == "hello" ]; then
これはスクリプトを壊します。解決策は、二重括弧を使用するか、常に変数を引用符で囲むことを忘れないでください("$var"
)。二重括弧は、より防御的なコーディング方法です。
[[
[
コマンドに似ていますが、より強力なbashキーワードです。
見る
http://mywiki.wooledge.org/BashFAQ/031およびhttp://mywiki.wooledge.org/BashGuide/TestsAndConditionals
POSIX shを作成しているのでない限り、をお勧めし[[
ます。
バッシュのマニュアルは言う:
[[と共に使用すると、 '<'および '>'演算子は、現在のロケールを使用して辞書式にソートされます。テストコマンドはASCII順序を使用します。
(テストコマンドは[]と同じです)