的命令時錯誤:括號子shell不工作存儲在一個變量
(echo: command not found
代碼:
input="(echo 1)"
$input
爲什麼它不評估括號以同樣的方式,把它放在當我這樣稱呼它的時候是一個子殼?
的命令時錯誤:括號子shell不工作存儲在一個變量
(echo: command not found
代碼:
input="(echo 1)"
$input
爲什麼它不評估括號以同樣的方式,把它放在當我這樣稱呼它的時候是一個子殼?
括號是shell語法。
要將反映爲將變量存儲在shell中進行處理的語法,必須使用eval
命令。
僅將變量值插入命令行不會觸發eval
語法評估。這將是eval的不必要的入侵,這會導致各種問題。
例如,考慮一下:
arg="(parenthesized)"
somecommand $arg
我們只是想somecommand
與字符串(parenthesized)
作爲它的參數來調用;我們不想運行子shell。這種隱含的評估會將無害的數據轉化爲實時代碼,從而產生安全漏洞,更不用說編碼噩夢來試圖避免它。
$arg
的處理規則與位置無關;膨脹發生即使$arg
是在命令行的第一個元素相同的方式:
$arg foo
參數替換變成$arg
到文本(parenthesized)
,然後被試圖作爲一個命令,而不是作爲一個殼的語法。
要執行的一塊存儲在input
shell腳本,使用:
eval "$input"
你也可以做這樣的:
input="echo 1" # no parentheses
/bin/sh -c "$input" # run in subshell explicitly
當然,子shell辦法飼料的代碼片段執行周圍腳本的同一個shell,而在這裏我們選擇了可能與調用shell不同的/bin/sh
,或者即使它是符號鏈接到同一個shell也具有不同的行爲。
由於'command'是一個內建函數,所以用它來代替some-random-other-command有點混亂 –
@CharlesDuffy先生,這是一個很好的觀點,它必須是固定的。 – Kaz
這在BashFAQ #50中詳細討論。
未引用的擴展只經歷了兩個shell解析階段:字段拆分和glob擴展。因此,(echo 1)
首先被分成字段:(
,echo
,1
和)
;每個擴展爲一個glob(模擬,因爲它們都不是glob擴展);然後將它們作爲命令運行:調用(
,第一個參數爲echo
,第二個參數爲1
,第三個參數爲)
。
正確的方式來存儲的代碼是在一個函數:
# best-practices approach
input() (echo 1;)
input
...或者,如果你想使之更加明確到人的讀者,你真的想一個子shell和間沒有」使用括號而非括號牛逼的錯誤或習慣:
# same, but more explicit about intent
input() { (echo 1); }
input
...如果無法實現,可以使用eval
(但要注意在BashFAQ #48給出警告的):
# avoid this approach if at all possible
input="(echo 1)"
eval "$input"
如果你在一個字符串建立一個命令的真正原因是參數化的內容,而是基於一個數組:
input_args=(1) # define an array
input() (echo "${input_args[@]}") # use that array in a function (if needed)
# add things according to conditional logic as appropriate
if ((2 > 1)); then
input_args+=("possible argument here")
fi
# call the function, or just use the array directly, such as: (echo "$(input_args[@]}")
input
參見[BashFAQ#50](HTTP:// mywiki.wooledge.org/BashFAQ/050)。一個沒有引號的擴展只經過兩個解析階段(場分割和全局擴展);這是非常好的理由(否則在bash中編寫安全代碼會更困難)。鏈接的常見問題解答詳細介紹,包括討論最佳實踐,以便您可能想將代碼存儲在變量中。 –
您不能將這些命令放入變量中。事實上,將命令放在變量中很容易失敗。變量包含_data_,而不是_命令!_如果您想將命令存儲在某處以備將來使用,請使用_function._ –
順便說一句,您的代碼和錯誤不會對齊。如果你使用了這裏提供的確切代碼,你會得到'(:command not found')。確保將你的問題中的代碼完全複製/粘貼到問題*中,以避免將來出現這種情況,這些差異實際上可能很重要 –