二重または単一の括弧、括弧、中括弧の使用方法


658

Bashでの角かっこ、かっこ、中かっこの使い方、およびそれらの二重形式と単一形式の違いに混乱しています。明確な説明はありますか?

回答:


606

Bashではtest[シェルビルトインです。

ダブルブラケットシェルのキーワードで、追加機能を可能にします。たとえば、&&andの||代わりに-aand -oを使用でき、正規表現一致演算子があり=~ます。

また、単純なテストでは、二重の角かっこは単一の角かっこよりもはるかに速く評価されるようです。

$ time for ((i=0; i<10000000; i++)); do [[ "$i" = 1000 ]]; done

real    0m24.548s
user    0m24.337s
sys 0m0.036s
$ time for ((i=0; i<10000000; i++)); do [ "$i" = 1000 ]; done

real    0m33.478s
user    0m33.478s
sys 0m0.000s

中括弧は、変数名の区切りに加えて、パラメーターの展開に使用されるため、次のようなことができます。

  • 変数の内容を切り捨てます

    $ var="abcde"; echo ${var%d*}
    abc
    
  • 次のように置き換えます sed

    $ var="abcde"; echo ${var/de/12}
    abc12
    
  • デフォルト値を使用

    $ default="hello"; unset var; echo ${var:-$default}
    hello
    
  • さらにいくつか

また、ブレース展開は、通常ループで繰り返される文字列のリストを作成します。

$ echo f{oo,ee,a}d
food feed fad

$ mv error.log{,.OLD}
(error.log is renamed to error.log.OLD because the brace expression
expands to "mv error.log error.log.OLD")

$ for num in {000..2}; do echo "$num"; done
000
001
002

$ echo {00..8..2}
00 02 04 06 08

$ echo {D..T..4}
D H L P T

先行ゼロおよびインクリメント機能は、Bash 4より前には利用できなかったことに注意してください。

ブレースの展開について思い出させてくれたgboffiに感謝します。

二重括弧は算術演算に使用されます

((a++))

((meaning = 42))

for ((i=0; i<10; i++))

echo $((a + b + (14 * c)))

また、整数変数と配列変数のドル記号を省略し、読みやすくするために演算子の前後にスペースを含めることができます。

単一のブラケットは配列インデックスにも使用されます:

array[4]="hello"

element=${array[index]}

中括弧は、右側の(ほとんど/すべて?)配列参照に必要です。

ephemientのコメントから、括弧はサブシェルにも使用されていることがわかりました。そして、それらは配列の作成に使用されます。

array=(1 2 3)
echo ${array[1]}
2

8
警告:その関数はフォーク爆弾です。実行しないでください。参照:en.wikipedia.org/wiki/Fork_bomb
追って通知があるまで一時停止。

3
追加ので起動した場合、それはフォーク爆弾だけです:
ephemient

7
また、完全を期すために、古いスクリプトでこれに遭遇しました$[expression]。これは、新しい、優先構文の古い、廃止予定の算術式の構文は次のとおりです。$((expression))
マイケル・

2
@DennisWilliamson中かっこの別の使用法はbash、以下で周辺的に言及されているように、シーケンスを作成することです(stackoverflow.com/a/8552128/2749397)この機能について少しコメントしたいので(あなたはそれについて言及しませんでした;-)私はm最も投票された回答を手段として使用する自由をとる...シーケンスリテラルの2つの例:echo {01..12}-> 01 02 03 04 05 06 07 08 09 10 11 12(最初のゼロに注意)。echo {C..Q}-> C D E F G H I J K L M N O P Q。その主な用途はループ内です。たとえば、 for cnt in {01..12} ; do ... ${cnt} ... ; done
gboffi 2014年

1
@gboffi:ゼロパディング機能はBash 4で使用可能になりました。また、Bash 4では、インクリメントを次の順序で指定できます:echo {01..12..2}-> "01 03 05 07 09 11"。シーケンスについてのリマインダーをありがとう。回答に追加します。
追って通知があるまで一時停止。

336
  1. 単一のブラケット([)は通常、実際にはというプログラムを呼び出し[ます。man testまたはman [詳細については。例:

    $ VARIABLE=abcdef
    $ if [ $VARIABLE == abcdef ] ; then echo yes ; else echo no ; fi
    yes
    
  2. 二重ブラケット([[)は単一ブラケットと(基本的に)同じことを行いますが、bash組み込みです。

    $ VARIABLE=abcdef
    $ if [[ $VARIABLE == 123456 ]] ; then echo yes ; else echo no ; fi
    no
    
  3. 括弧(())はサブシェルを作成するために使用されます。例えば:

    $ pwd
    /home/user 
    $ (cd /tmp; pwd)
    /tmp
    $ pwd
    /home/user
    

    ご覧のとおり、サブシェルを使用すると、現在のシェルの環境に影響を与えることなく操作を実行できます。

  4. (a)中括弧({})は、変数を明確に識別するために使用されます。例:

    $ VARIABLE=abcdef
    $ echo Variable: $VARIABLE
    Variable: abcdef
    $ echo Variable: $VARIABLE123456
    Variable:
    $ echo Variable: ${VARIABLE}123456
    Variable: abcdef123456
    

    (b)中括弧は、現在のシェルコンテキストでコマンドのシーケンスを実行するためにも使用されます。

    $ { date; top -b -n1 | head ; } >logfile 
    # 'date' and 'top' output are concatenated, 
    # could be useful sometimes to hunt for a top loader )
    
    $ { date; make 2>&1; date; } | tee logfile
    # now we can calculate the duration of a build from the logfile
    

( )ただし、構文には微妙な違いがあります(bashリファレンスを参照)。基本的に、セミコロン;括弧内の最後のコマンドの後には必須で、中括弧は{} しなければならないスペースに囲まれて。


26
まあ、[実際にはBashの組み込みですが、組み込みとは/bin/[対照的に動作するはず[[です。 [[より論理的な操作や異なる引用の役割など、さまざまな機能があります。さらに、単一の括弧は、配列、プロセス置換、および拡張グロブにも使用されます。二重括弧は算術に使用されます。中かっこ{}は、コマンドのグループ化、またはパラメータ展開、ブレース展開、シーケンス展開のタイプの多数に使用されます。私は他のいくつかの用途も見逃していたと確信しています...
ephemient

4
式の中の二重のイコールif [ $VARIABLE == abcdef ]は、バシズムです-これは機能しますが-おそらく避けるべきです。明示的にbash(if [[ ...==...]])を使用するか、より伝統的な条件付き(if [ "$VARIABLE" = "abcdef" ])を使用していることを明確にします。おそらく、スクリプトは、(何らかの理由で)bashに固有の機能が本当に必要になるまで、できるだけ単純で移植性のあるものから始めるべきです。しかし、いずれにしても、意図は明確でなければなりません。"="と "=="と "[["と "["は動作が異なり、使用方法は一貫している必要があります。
マイケル

3
@michael_n:この発言の+1。余談ですが、スクリプトは大好きですが、移植可能な方法はの[ "$var" = ".."]代わりにを介してテストするのがかなり厄介ですが、==Cの場合はテストの代わりに割り当てます(そして、バグのかなり一般的な原因です)...の代わりにtest使用しませんか?誰か知ってる?===
Olivier Dulac 2013年

また、ここでは(少なくともKubuntuでは)コマンド/usr/bin/[がへのシンボリックリンクではない、という興味深い点が/usr/bin/testあります。これらのプログラムには、いくつかの異なるサイズさえあります!
Hi-Angel

また、単一の閉じ括弧)case、case行を終了するステートメント構文の一部です。左括弧はありません。これは私がそれを初めて見たとき私を失望させました。
アグスティンAmenabar

302

ブラケット

if [ CONDITION ]    Test construct  
if [[ CONDITION ]]  Extended test construct  
Array[1]=element1   Array initialization  
[a-z]               Range of characters within a Regular Expression
$[ expression ]     A non-standard & obsolete version of $(( expression )) [1]

[1] http://wiki.bash-hackers.org/scripting/obsolete

中かっこ

${variable}                             Parameter substitution  
${!variable}                            Indirect variable reference  
{ command1; command2; . . . commandN; } Block of code  
{string1,string2,string3,...}           Brace expansion  
{a..z}                                  Extended brace expansion  
{}                                      Text replacement, after find and xargs

括弧

( command1; command2 )             Command group executed within a subshell  
Array=(element1 element2 element3) Array initialization  
result=$(COMMAND)                  Command substitution, new style  
>(COMMAND)                         Process substitution  
<(COMMAND)                         Process substitution 

二重括弧

(( var = 78 ))            Integer arithmetic   
var=$(( 20 + 5 ))         Integer arithmetic, with variable assignment   
(( var++ ))               C-style variable increment   
(( var-- ))               C-style variable decrement   
(( var0 = var1<98?9:21 )) C-style ternary operation

@ヨラ、$(varname)は何を正確に説明できますか?Apple Xcodeプロジェクトでは、スクリプトの入出力としてファイルパスを指定できます。$ SRC_ROOT / myFile.txtまたは$ {SRC_ROOT} /myFile.txtを指定した場合(SRC_ROOT変数はビルドシステムによってエクスポートされます)-機能しません。$(SRC_ROOT)/myFile.txtのみが機能します。その理由は何でしょうか?明らかにvar nameはコマンドではありませんか?
Motti Shneor

1
@MottiShneor、あなたの場合$(varname)、bash構文とは無関係です。Makefile構文の一部です。
サーシャ2017

そうではありません-Xcodeはmakefileを使用してビルドしておらず、その変数は環境変数です。独自のXcodeビルドシステムプロセスは、これらの事前定義された環境変数の値を読み取ります。カスタムビルドステップは、通常のシェルスクリプト(bashまたはその他)であり、同じ変数にアクセスできます。
Motti Shneor

@MottiShneor、わかりました、改良してみましょう。おそらくこれはxcconfig構文の一部です。とにかく、$(varname)あなたの場合、bash構文とは関係ありません。
サーシャ2017年

テストコンストラクトと拡張テストコンストラクトの違いは何も述べていません。
ニコス2017

23

これらをTLDPから追加したかっただけです

~:$ echo $SHELL
/bin/bash

~:$ echo ${#SHELL}
9

~:$ ARRAY=(one two three)

~:$ echo ${#ARRAY}
3

~:$ echo ${TEST:-test}
test

~:$ echo $TEST


~:$ export TEST=a_string

~:$ echo ${TEST:-test}
a_string

~:$ echo ${TEST2:-$TEST}
a_string

~:$ echo $TEST2


~:$ echo ${TEST2:=$TEST}
a_string

~:$ echo $TEST2
a_string

~:$ export STRING="thisisaverylongname"

~:$ echo ${STRING:4}
isaverylongname

~:$ echo ${STRING:6:5}
avery

~:$ echo ${ARRAY[*]}
one two one three one four

~:$ echo ${ARRAY[*]#one}
two three four

~:$ echo ${ARRAY[*]#t}
one wo one hree one four

~:$ echo ${ARRAY[*]#t*}
one wo one hree one four

~:$ echo ${ARRAY[*]##t*}
one one one four

~:$ echo $STRING
thisisaverylongname

~:$ echo ${STRING%name}
thisisaverylong

~:$ echo ${STRING/name/string}
thisisaverylongstring

18
マインドというecho ${#ARRAY}理由の最初の要素のディスプレイ3には、ARRAYそれは3つの要素が含まれていないので、3つの文字が含まれています!要素の数を出力するには、を使用しますecho ${#ARRAY[@]}
TrueY 2013

@zeal ${TEST:-test}$TEST、変数TESTが存在する場合は等しく、それ以外の場合は単に文字列「test」を返します。さらに多くの機能を実行する別のバージョンがあります${TEST:=test}。--- $TESTTESTが存在する場合と同じですが、存在しない場合は常に変数TESTを作成して値「test」を割り当て、式全体の値になります。
確率を愛する

18

test[[[の違いは、BashFAQで詳細に説明されています

長い話を簡単に言うと、テストはコマンドの古い、移植可能な構文を実装しています。ほとんどすべてのシェル(最も古いBourneシェルは例外です)では、[はテストの同義語です(ただし、最後の引数として]が必要です)。最近のすべてのシェルには、[の組み込み実装がありますが、通常、その名前の外部実行可能ファイル(例:/ bin / [)がまだあります。

[[は、その改良版であり、プログラムではなくキーワードです。これは、次に示すように、使いやすさに有益な効果をもたらします。[[はKornShellとBASH(例えば2.03)で理解されますが、古いPOSIXやBourneShellでは理解されません。

そして結論:

いつ新しいテストコマンド[[を使用し、いつ古いコマンド[?BourneShellへの移植性が懸念される場合は、古い構文を使用する必要があります。一方、スクリプトでBASHまたはKornShellが必要な場合、新しい構文ははるかに柔軟です。


18

関数定義の括弧

括弧()は関数定義で使用されています:

function_name () { command1 ; command2 ; }

これが、コマンドパラメーターでも括弧をエスケープする必要がある理由です。

$ echo (
bash: syntax error near unexpected token `newline'

$ echo \(
(

$ echo () { command echo The command echo was redefined. ; }
$ echo anything
The command echo was redefined.

ああ、私はcshで試しました。私の悪い。私がbashを試してみると、うまくいきます。bashのコマンド「command」を知りませんでした。
Chan Kim

コマンドecho()の再定義をキャンセルするにはどうすればよいですか?(bashを再度開くことなく)
Chan Kim

2
@ChanKim: unset -f echo。を参照してくださいhelp unset
pabouk 2015

0
Truncate the contents of a variable

$ var="abcde"; echo ${var%d*}
abc

Make substitutions similar to sed

$ var="abcde"; echo ${var/de/12}
abc12

Use a default value

$ default="hello"; unset var; echo ${var:-$default}
hello

質問に答えるときは、「コード」を目的とするだけでなく、説明も追加してみてください...
Mikev
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.