web-dev-qa-db-ja.com

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

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

たとえば、私は次のことを見ました。

var=10        # Declare variable

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

大きな違いはありますか、それとも単なるスタイルですか。一方が他方よりも優先されますか。

547
New User

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

"${foo}bar"

"$foobar"は代わりにfoobarで識別される変数を展開します。

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

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

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

628
Fred Foo

変数は、$および{}なしで宣言および代入されます。あなたが使用する必要があります

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はあなたが思うようなことをしません!

114
Aaron McDaid

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

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

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

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

結果:

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

または

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

結果:

This_is_a_string

あなたは「通常の変数」に正当である必要はありません。

25
SierraX

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

古典的な例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

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

9

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 変数の内容を new_Word の内容に置き換えます。

> sed -i "s/${Word}/${new_Word}/g" $sposi
> cat $sposi

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

単語 "ramo"は置き換えられました。

1
Fabio Natalini

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

あいまいさの余地がない場合でも、過度に用心深くないことと、シェル変数の展開に{}を使用することは良いことです。

例えば:

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
codeforester