引用する

引用する

私は書くことができます

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

私にとって最終結果はほぼ同じようです。なぜこれらのことの1つを書くべきですか?移植可能/POSIXではないものはありますか?

答え1

VAR=$VAR1はい、単純化されたバージョンですVAR=${VAR1}。 2つ目はできますが、1つ目はできません。たとえば、配列インデックス参照(移植可能ではない)や部分文字列の削除(POSIX - 移植可能)などがあります。より変数に関する追加情報Bash初心者ガイドの一部パラメータ拡張POSIX仕様で。

変数の周りに引用符を使用することをお勧めします(例:rm -- "$VAR1"orの引用符)。rm -- "${VAR}"これは変数の内容を原子単位にします。変数の値に空白($IFS特殊変数の文字、デフォルトでは空白)またはワイルドカード文字が含まれていて、引用符を付けないと、各単語がファイル名の生成(ワイルドカード)で考慮され、拡張が実行されます。あなたは仕事を。

$ 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、中括弧はオプションです。

答え2

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

csh、tcsh、またはzsh(ksharraysオプションが有効になっていない場合)はand$var[1]と同じであるため、リテラルの後に:または:を拡張するには中括弧も必要です。${var[1]}$var:modifier${var:modifier}$var[1]:modifier${var}[1] ${var}:modifier

スカラー(配列または連想配列とは反対)の変数割り当てでは、フィールド分割(つまり、値の空白に分割)パス名拡張(つまり、globbing)はオフになっているので、私が聞いたすべてのPOSIXシェルとすべてのPOSIX以前のshsVAR=$VAR1とまったく同じです。VAR="$VAR1"(POSIXを参照:簡単なコマンド)。もちろん、同じ理由でリテラル文字列にVAR=*設定されます。なぜなら、theは最初に単一の単語だからです。通常、シェル構文に単一の単語が必要な場合は、二重引用符は必要ありません。VAR*VAR=a bVARab存在するcase … in(しかしスキーマにはない)そこでも注意が必要です。例: POSIX は次のように指定します。リダイレクト先>$filename)はスクリプトに引用符を必要としませんが、一部のシェル(bashを含む)はスクリプトでも二重引用符を要求します。バラよりいつ二重引用符が必要ですか?より徹底的な分析のために。

export VAR="${VAR1}"特に、同等に作成できる多くのシェルで二重引用符が必要な場合がありますexport "VAR=${VAR1}"(POSIXではこのケースを予約します)。このケースは、単純な割り当てに似ており、二重引用符を必要としないケースリストの分散特性のため、分割とワイルドカードを本当に望まない限り、二重引用符を使用することをお勧めします。

答え3

引用する

変数の拡張には二重引用符を、拡張子のない二重引用符には一重引用符を検討してください。

拡張:

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

出力:

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

さまざまな理由で可能な場合は必ず引用符を使用する必要があることに言及する価値があります。その中で最も良いのは、それがベストプラクティスと見なされ、読みやすさが高いことです。また、Bashは時々非論理的であるか、非合理的/予期しないように見えるように気まぐれになる可能性があるため、引用すると暗黙の期待が明示的に変わり、エラー表面(またはそれに伴うエラーの可能性)が減少します。

これは完全に合法的ですが、いいえ引用してみてください。ほとんどの場合は機能しますが、この機能は便宜上提供されているため、移植性が悪い場合があります。意図と期待を反映することが保証される完全に正式なアプローチは引用です。

置換

"${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シェルスクリプトへの権威ある参照は、libreオンライン参照であるTLDP Linuxドキュメントプロジェクトです。https://www.tldp.org/LDP/abs/html/parameter-substitution.html

関連情報