3

コマンド置換の出力をループし、ループ本体内で別のコマンド置換を実行しようとする bash スクリプトを作成しています。コードは次のとおりです。

#!/usr/bin/bash

IFS=$'\n' 

for i in $( xmllint --xpath "string(/*[local-name()='Project'])" gsGDAL/gsGDAL.vcxproj.user )
do
   IFS=' ' #attempted with and without this line
   "$( awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i) )"
   IFS=$'\n' #attempted with and without this line
done

IFS を newline に設定して、ループがスペースで区切られた各単語を反復するのではなく、xmllint コマンドの出力の各行を反復するようにします。ただし、これにより、ループ内のコマンド置換が失敗します。デバッグの結果、問題の本質は次のとおりであるという結論に達しました。

#!/usr/bin/bash

IFS=$'\n'

$(echo export TEST="test")

エラーが発生します:

./x.sh: line 6: export TEST=test: command not found

ループ内で IFS をリセットすることにより、最初のコード例で修正を試みたことがわかります。それはうまくいきませんでした。

スクリプトの別のイディオムを使用して問題を解決できることに気付きました。
たとえば、1 つの可能性を示すために、個々の行で awk を実行する代わりに、xmllint コマンドを awk に置き換えるプロセス。その趣旨のコメントは大歓迎ですが、以下に関連する回答を提出してください。

  1. IFS を改行に設定すると、コマンド置換で生成されたエクスポートが台無しになるのはなぜですか?
  2. ループ内で IFS をリセットしても問題が解決しないのはなぜですか?

更新: Barmar との議論によると、IFS はコマンド/変数展開後の単語分割に使用されます。

4

2 に答える 2

4

IFSあなたの問題の原因ではないと思います。コードには 2 つの問題があります。

  1. 二重引用符を入れる$(awk ...)ので、単語の分割は行われません。したがってexport varname="value"、コマンドの名前として扱われます。スペースはコマンド名の一部であり、コマンドと引数の間の区切りではありません。

  2. 二重引用符がなくても、コマンド置換の結果に対して引用符処理が実行されず、単語分割とワイルドカード展開のみが実行されるため、機能しません。したがって、exportコマンドの二重引用符は、割り当てられる値にリテラル文字として含まれます。

これに対する解決策は、mplf で指摘されているように、次を使用することevalです。

eval "$(awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i) )"
于 2013-06-13T01:22:49.027 に答える
2

evalサブシェルから返される文字列を評価するために使用します。

IFS=' ' #attempted with and without this line
eval $( awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i) )
IFS=$'\n' #attempted with and without this line
于 2013-06-13T00:52:11.130 に答える