2013-06-13 66 views
2

我寫遍歷一個命令替換的輸出,然後嘗試循環體內執行其他命令替換bash腳本。下面是代碼:Bash的IFS變量如何影響命令替換?

#!/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爲換行符,使經過xmllint命令的輸出,而不是遍歷每個空格分隔單詞的每行的循環迭代。 但是,這會使循環內的命令替換失敗。一些調試得出的結論是,問題的實質是:

#!/usr/bin/bash 

IFS=$'\n' 

$(echo export TEST="test") 

這給錯誤:

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

你可以看到,我試圖在第一個代碼示例修復通過重置IFS在循環內。這沒有用。

我知道我可以使用腳本不同的成語解決問題。
例如過程將xmllint命令替換爲awk,而不是在每行上執行awk命名一種可能性。 評論該效果是值得歡迎的,但請提交答案相關的以下內容:

  1. 爲什麼IFS設置爲換行符弄亂產生出口的命令替換?
  2. 爲什麼重置IFS在循環不解決這一問題?

UPDATE: 每與Barmar的討論中,IFS被用於後命令/變量擴展詞分割。

回答

4

我不認爲IFS是你的問題的原因。有兩個問題與您的代碼:

  1. 您在雙引號把$(awk ...),所以沒有分詞做。所以它把export varname="value"作爲命令的名稱 - 空間是命令名稱,而不是命令和參數之間的分隔符的一部分。

  2. 即使沒有雙引號,它不會因爲命令替換的結果,不進行報價處理工作,只有分詞和通配符擴展完成。因此,export命令中的雙引號將作爲文字字符包含在分配的值中。

解決這一點,因爲通過MPLF指出的那樣,是用eval

eval "$(awk -F= '{printf("export %s=\"%s\"", $1, $2)}' <(echo $i))" 
+0

謝謝。我想知道你是否能告訴我爲什麼把IFS設置爲換行防止命令替換結果正確執行。難道是因爲shell使用IFS來標記命令,造成'出口TEST =「測試」'解析過程中被解釋爲一個單一的令牌?而且,如果是這樣,爲什麼eval不受此限制(當我使用eval時,我的代碼沒有將IFS重置爲空格)? – user2141130

+0

是的,沒錯。在解析命令行時,shell使用分詞來查找命令 - 它只是第一個單詞。如果您更改單詞分割的參數,則會影響此操作。 – Barmar

+0

太好了,謝謝。 eval是否不使用IFS? – user2141130

2

使用eval評估字符串從子shell返回。

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