web-dev-qa-db-ja.com

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

このbashを考えると:

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

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

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

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

12
neuviemeporte

違いがあります:

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

そして

... --exclude='.git'

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

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

ただし、この種の場合は array の方が適しています。

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

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

17
Michael Homer

@ Michael Homer's answer に加えて、basheval function を使用できます。

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