web-dev-qa-db-ja.com

$ VAR対$ {VAR}および引用するかしないか

私は書くことができます

VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"

私にとっての最終結果はすべてほぼ同じようです。なぜどちらかを書く必要があるのですか?これらのいずれかはポータブル/ POSIXではありませんか?

150
xenoterracide

VAR=$VAR1VAR=${VAR1}の簡易バージョンです。たとえば、配列インデックスの参照(移植不可)や部分文字列の削除(POSIX移植可能)など、2番目の方法では最初の方法ではできません。 Bash Guide for Beginnersの More on variables セクションおよびPOSIX仕様の Parameter Expansion を参照してください。

rm -- "$VAR1"またはrm -- "${VAR}"のように、変数を引用符で囲むことは良い考えです。これにより、変数の内容が原子単位になります。変数の値に空白($IFS特殊変数の文字、デフォルトでは空白)または引用文字を含まない場合、各Wordはファイル名の生成と見なされ(展開)、次のようになります。あなたがやっていることへの多くの議論。

$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'

$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename

移植性について: POSIX.1-2008セクション2.6.2 によると、中括弧はオプションです。

108
Shawn J. Goff

${VAR}$VARはまったく同じです。単純な変数展開の場合、${VAR}を使用する唯一の理由は、${VAR1}_$VAR2(中かっこなしでは${VAR1_}$VAR2と同等)のように、解析によって変数名に文字が多すぎる場合です。 )。ほとんどの装飾された拡張(${VAR:=default}${VAR#prefix}、…)には中括弧が必要です。

変数の割り当てでは、 フィールド分割 (つまり、値の空白で分割)および パス名展開 (つまり、グロビング)がオフになっているため、VAR=$VAR1はまったく同じですVAR="$VAR1"に、すべてのPOSIXシェルと私が聞いたすべてのPOSIX以前のshで。 (POSIX ref: simple commands )。同じ理由で、VAR=*は確実にVARをリテラル文字列*に設定します。もちろんVARは最初から独立した単語であるため、VAR=a babに設定します。一般的に言えば、シェル構文が単一の単語を期待する場合、二重引用符は必要ありません。たとえば in case … in (ただしパターンには含まれません)。ただし、ここでも注意する必要があります。たとえばPOSIXは リダイレクトターゲット>$filename)はスクリプトでの引用を必要としないと規定していますが、bashを含むいくつかのシェルはスクリプトでも二重引用符を必要とします。より詳細な分析については、 ダブルクォートが必要な場合 を参照してください。

他の場合、特に多くのシェルでexport VAR="${VAR1}"(同等にexport "VAR=${VAR1}"と書くことができます)の場合は、二重引用符が必要です(POSIXはこのケースを開いたままにします)。このケースの単純な割り当てとの類似性、および二重引用符が不要なケースのリストの点在する性質は、分割してグロブしたくない場合を除いて、二重引用符を使用することをお勧めします。

引用

二重引用符は変数の展開に使用され、単一引用符は強い引用符、つまり展開ではなく使用されることを考慮してください。

拡張:

this='foo'
that='bar'
these="$this"
those='$that'

出力:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

いくつかの理由から可能な限り引用を使用する必要があることを言及することは価値があるかもしれません。その中で最も良いのは、それがベストプラクティスと考えられていることと読みやすさのためです。また、Bashは時々奇妙に見える場合があり、一見すると非論理的または不合理な/予期しない方法で風変わりであり、引用は暗黙の期待を明示に変更するため、エラーサーフェス(またはその可能性)が減少します。

notの引用は完全に合法であり、ほとんどの場合機能しますが、その機能は便宜上提供されており、おそらく移植性が低くなります。意図と期待を反映することが保証された完全に正式な慣行は引用することです。

代用

次に、コンストラクト"${somevar}"は、置換演算に使用されます。置換や配列などのいくつかの使用例。

交換(ストリッピング):

thisfile='foobar.txt.bak'
foo="${thisfile%.*}"   # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}"  # removes longest matching

for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar

交換(交換):

foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}"   #single occurrence
bar="${foobar//least/most}"  #global occurrence (all)

for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful

配列:

mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls  
alpha=($(ls temp/*))

echo "$alpha"         #  temp/foo.txt
echo "${alpha}"       #  temp/foo.txt
echo "${alpha[@]}"    #  temp/bar.txt  temp/foobar.txt  temp/foo.txt
echo "${#alpha}"      #  12 # length of first element (implicit index [0])
echo "${#alpha[@]}"   #  3  # number of elements
echo "${alpha[1]}"    #  temp/foobar.txt # second element
echo "${#alpha[1])"   #  15 # length of second element

for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt

これらすべてが"${var}"置換コンストラクト。 Bash Shellスクリプティングの最も信頼できるリファレンスはlibreオンラインリファレンス、TLDPです。TheLinux Documentation Project https://www.tldp.org/LDP/abs/html/parameter-substitution.html

9
SYANiDE
ls -la

lrwxrwxrwx.  1 root root      31 Nov 17 13:13 prodhostname
lrwxrwxrwx.  1 root root      33 Nov 17 13:13 testhostname
lrwxrwxrwx.  1 root root      32 Nov 17 13:13 justname

次に終了:

env=$1
    if [ ! -f /dirname/${env}hostname ]

カーリーの使用のより明確な例として言及する価値がある

0
ninjabber