パラメーターリストの作成に使用されるbash文字列の連結


12

次のbashを考えます:

PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo $PARMS
rsync ${PARMS} . ${TARGET}

エコーはPARMS文字列を期待どおりに表示し、エラーは表示されませんが、rsyncは+ =によって追加されたオプションが存在しないかのように静かに動作します。ただし、これは期待どおりに機能します。

PARMS='-rvu'
rsync ${PARMS} --delete --exclude='.git' . ${TARGET}

私はbash引用符で何かを台無しにしたと思います(常にそれらに問題がありました)が、文字列が正しく構築されているように見えても、オプションが何を無視するのか正確にはわかりません。


1
echo "$PARMS"そして、rsync "${PARMS}"...
jasonwryan

これは、bashバージョン4.2.25で変更なしで機能します。
アントン14

回答:


17

次の間に違いがあります。

PARMS+="... --exclude='.git'"

そして

... --exclude='.git'

最初の例では、単一引用符は引用符自体の中にあるため、rsync引数として指定された置換テキストに文字通り存在します。rsync値がの引数を取得します--exclude='.git'。2番目では、単一引用符は、引用符自体の中になく、参照できるため、記述時にシェルによって解釈さrsyncれます--exclude=.git

この場合、一重引用符はまったく必要ありません。.gitそれ自体が完全に有効なシェルワードであり、特殊文字はないため、コマンドで文字通り使用できます。

ただし、この種の場合には配列のほうが優れています。

PARMS=(-rvu)
PARMS+=(--delete --exclude='.git')
rsync "${PARMS[@]}"

これにより、コマンドを個別の単語として作成し、配列行を書き込むときに引用したいものを解釈します。引数自体に特殊文字やスペースが含まれている場合でも、配列内の各エントリに個別の引数として"${PARMS[@]}"展開されるため、rsync意図したとおりに記述した内容が表示されます。


bash${PARMS}展開後に単語分割を実行しました。したがって、単一引用符もシェルによって解釈されました。
クオンルム14

2
それを試してみてください!やった。引用符は残りますが、間にスペースがあった場合、それらはとにかく分割されます。
マイケルホーマー14

@Gnouc:bashのmanページから:「引用の除去:前の拡張後は、すべて引用符で囲まれていない文字の出現\ 'および"その上の展開のいずれかから生じなかったが削除されます。」「上記の展開」には、の展開を実行するパラメータ展開が含まれ${PARMS}ます。
カム14

ありがとう。だから、その場合、二重引用符内の単一引用符を省略しても機能することを理解していますが、完全性のために-特殊文字を引用する必要があり、後者のアプローチを使用したくない場合はどうなりますか?
neuviemeporte

特殊文字がIFS(通常、空白文字)の一部ではない場合、引用符で囲む必要はありません。もしそうなら、一緒に何かをハックしない限り、あなたは運が悪いeval-これは一般にちょっとした特徴であり、配列はそれに対処する正しい方法です。
マイケルホーマー14

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.