シェル変数を中括弧で囲む必要があるのはいつですか?


659

シェルスクリプトでは、{}変数を展開するときにいつ使用しますか?

例えば、私は以下を見ました:

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable

大きな違いはありますか、それとも単なるスタイルですか?どちらが優先されますか?

回答:


753

この特定の例では、違いはありません。ただし、{}in ${}foo、文字列内の変数を展開する場合に便利です。

"${foo}bar"

以来、"$foobar"代わりにより識別される変数を拡大しますfoobar

中括弧は、次の場合にも無条件に必要です。

  • 配列要素の拡張 ${array[42]}
  • ${filename%.*}(拡張の削除)のように、パラメーター拡張操作を使用する
  • 位置パラメータを9を超えて拡張: "$8 $9 ${10} ${11}"

あいまいな可能性がある場合だけでなく、どこでもこれを行うことは、優れたプログラミング手法と見なすことできます。これは、一貫性を保つため$foo_$bar.jpgと、アンダースコアが変数名の一部になることが視覚的に明白でないのような驚きを避けるためです。


106
{}ブレース拡張として知られています。${}変数展開として知られています。彼らは異なることをします。拡張なしのビットを除いて、私はあなたに賛成票を投じます。
Spencer Rathbun、2012年

5
@NewUser「したがって、配列以外では、実際には必要ありません」そうではないので、スクリプトで非常に便利な構文であるPARAMETER EXPANSIONには中括弧が必要です。sedとawkのスクリプトをたくさん見て、少しパラメーターを拡張することで置き換えることができます。
SiegeX 2012年

10
@caffinatedmonkey $()md5sum=$(md5sum foo.bin)、の出力をmd5sum foo.bin変数md5sumに格納するコマンドを実行するために使用され、を使用してアクセスできるようになりました${md5sum}。また、明示的にすることは良い習慣であることを言及するために、OPに対して+1やその他多くのことを精神的に!
L0j1k

11
@ L0j1k明示的に言えば$()サブシェルからコマンドを実行することに言及することが重要です。
エイドリアンGünter

2
@karatedog ${1:-20}は、パラメーター拡張の形式です。それは主に数字と関与算術あり思考で私たちをだまし算術演算子を使用しているため、ここでは明らかではないが、それは実際には位置パラメータを指し、$1デフォルト値に置き換えられます定義されていない場合は、20(構文があります${variable:-default_value})。
アーロン

126

変数は$、なしで宣言され、割り当てられ{}ます。あなたが使用する必要があります

var=10

割り当てます。変数から読み取る(つまり、変数を「展開する」)には、を使用する必要があります$

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

これは私をときどき混乱させました-他の言語では、代入の左か右かに関係なく、同じ方法で変数を参照します。しかし、シェルスクリプトは異なり、$var=10あなたが思っているようなことはしません!


34

{}グループ化に使用します。中括弧は、配列要素を逆参照するために必要です。例:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect

最初の行が理解できませんでしたdir=(*)。私の知る限り、dirは、ディレクトリの内容を一覧表示する組み込みコマンドです(と同等ls -C -b)。説明していただけますか?
ジャービス

1
シェルプログラミングでは、コマンドと引数は空白で互いに分離する必要があります。ここでは、空白のない等号が表示されています。これは変数の割り当てであることを意味します。 dirは変数の名前で、括弧はファイル名の展開*を配列に収集するために使用されます。
グレン・ジャックマン

27

中括弧内でテキスト操作を行うこともできます。

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

結果:

./folder/subfolder/file.txt ./folder

または

STRING="This is a string"
echo ${STRING// /_}

結果:

This_is_a_string

あなたは正しい「通常の変数」は必要ありません...しかし、それはデバッグとスクリプトを読むのにより役立ちます。


11

変数名の終わりは、通常、スペースまたは改行で示されます。しかし、変数値を出力した後にスペースや改行が必要ない場合はどうでしょうか。中括弧は、変数名の終わりがシェルインタープリターにどこにあるかを伝えます。

古典的な例1)-末尾に空白がないシェル変数

TIME=10

# WRONG: no such variable called 'TIMEsecs'
echo "Time taken = $TIMEsecs"

# What we want is $TIME followed by "secs" with no whitespace between the two.
echo "Time taken = ${TIME}secs"

例2)バージョン管理されたjarを含むJavaクラスパス

# WRONG - no such variable LATESTVERSION_src
CLASSPATH=hibernate-$LATESTVERSION_src.zip:hibernate_$LATEST_VERSION.jar

# RIGHT
CLASSPATH=hibernate-${LATESTVERSION}_src.zip:hibernate_$LATEST_VERSION.jar

(フレッドの答えはすでにこれを述べていますが、彼の例は少し抽象的すぎます)


5

中括弧は、配列要素にアクセスしてブレース展開を実行するために常に必要です。

{}あいまいさの余地がない場合でも、過度に慎重にならず、シェル変数の展開に使用することをお勧めします。

例えば:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_arch       # {} is needed since _ can be a part of shell variable name

したがって、3行を次のように記述することをお勧めします。

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

これは間違いなくもっと読みやすいです。

変数名は数字で始めることはできないため、シェルは、そのような展開の後に数字が続く場合を除き、{}番号付き変数(など)を必要としません。それは微妙であり、そのようなコンテキストで明示的に使用することになります:$1$2{}

set app      # set $1 to app
fruit=$1le   # sets fruit to apple, but confusing
fruit=${1}le # sets fruit to apple, makes the intention clear

見る:


1
It's good to be not over-cautious:ほとんどの人がどう思うかしら。中かっこは常に使用して、必要なときに忘れないようにするか、必要な場合にのみ使用して、読みやすさを向上させます。
ロジャーダール

1
プログラマがカーリーを必要としない場合でも、カーリーを使用するようになるのは意識の欠如だと思います。この無知は、不注意な単語の分割やグロブを防ぐために二重引用符を使用しないという他の一般的な間違いに似ています。その根底にある現実は、プログラマーはシェルスクリプトについて、PythonやRubyなどの他のスクリプト言語ほど真面目ではないということです。
codeforester

1
本当です。私のペットpeeveは、誰もがすべての変数が:)シェルスクリプトですべて大文字であることを考えているようだある
ロジャー・ダール

2

テキストの操作に関するSierraXとPeterの提案に従って、中括弧{}はコマンドに変数を渡すために使用されます。例えば:

有名なイタリアの小説の最初の行を含むsposi.txtファイルがあるとします。

> sposi="somewhere/myfolder/sposi.txt"
> cat $sposi

出力: quel ramo del lago di como che volge a mezzogiorno

次に、2つの変数を作成します。

# Search the 2nd word found in the file that "sposi" variable points to
> word=$(cat $sposi | cut -d " " -f 2)

# This variable will replace the word
> new_word="filone"

sposi.txtファイル内のword変数contentをnew_wordの1つで置き換えます

> sed -i "s/${word}/${new_word}/g" $sposi
> cat $sposi

出力: quel filone del lago di como che volge a mezzogiorno

「ramo」という単語は置き換えられました。


1
これは、変数を中括弧で囲まなくても機能します。
Armali 2018

weel-known novelビットを修正したい場合があります。それでも賛成票を投じた。
gsl
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.