這是一個最小的例子:
#!/bin/bash
testFunc() (
shopt -s extglob
local posArgs=();
for((i=1; i<="$#"; i))
do
posArgs =("${!i}");
done
#<uncomment to see> echo "${posArgs[@]:0:$((${#posArgs[@]} - 1))}";
if ${posArgs[@]:0:$((${#posArgs[@]} - 1))};
then
return 0;
fi
return 1;
)
- 函式體使用
()而不是{}限制shopt的范圍 - 函式丟棄最后一個引數并執行其余引數并檢查退出代碼,如果 0 回傳 0,否則回傳 1。引號和命令替換不是故意使用的。
這是有效的:
testFunc "echo" "whatever" "discardThis"; #whatever
testFunc "pidof" "memcached" "discardThis"; #12435
testFunc "pwd" "discardThis"; #path/to/pwd
testFunc "pwd" "discardThis"; #path/to/pwd
testFunc "/bin/bash" "-c" "pwd" "discardThis"; #path/to/pwd
testFunc "/bin/bash" "-c" "pwd;pwd" "discardThis"; #path/to/pwd\npath/to/pwd NOTE:no space between ; and pwd
這是不起作用的:
testFunc "/bin/bash" "-c" "[[ 2 -eq 2 ]]" "discardThis"; #error
testFunc "/bin/bash" "-c" "\"[[ 2 -eq 2 ]]\"" "discardThis"; #error
testFunc "/bin/bash" "-c" "\"echo helloo\"" "discardThis"; #error
testFunc "/bin/bash" "-c" "echo helloo" "discardThis"; #exits with 0 but logs nothing
testFunc "/bin/bash" "-c" "pwd; pwd" "discardThis"; #logs pwd ONCE
testFunc "/bin/bash" "-c" "\"pwd; pwd\"" "discardThis"; #error
上面的日志錯誤如下:helloo": -c: line 0: unexpected EOF while looking for matching...
有趣的是,要使上述作業正常,您可以通過eval:
testFunc "eval" "/bin/bash" "-c" "\"echo helloo\"" "discardThis"; #helloo
testFunc "eval" "/bin/bash" "-c" "\"[[ 2 -eq 2 ]]\"" "discardThis"; #exits with 0
testFunc "eval" "/bin/bash" "-c" "pwd; echo haha; pwd;" "discardThis"; #path/to/pwd\nhaha\npath/to/pwd
testFunc "eval" "/bin/bash" "-c" "pwd; pwd" "discardThis"; #Correctly logs pwd TWICE
好像有一個像echo這樣的命令需要一個引數,或者需要一些其他復雜eval的命令。我怎樣才能避免這種情況?我怎樣才能讓它們在沒有 eval 的情況下作業。
我對實作我想要的東西不感興趣,我對為什么bin/bash無法決議像echo hi.
uj5u.com熱心網友回復:
為什么 bin/bash 無法決議像 echo hi 這樣的字串。
如果您對以下原因感興趣(不在您的示例中):
testFunc "/bin/bash" "-c" "echo hi" "discardThis"
什么都不輸出,然后讓我們深入研究:
${posArgs[@]:0:$((${#posArgs[@]} - 1))
未參考擴展的結果會進行分詞(和檔案名擴展!幸運的是,您沒有使用 進行測驗*)。無論您輸入什么,單詞拆分都會拆分空格(以及制表符和換行符,默認為 IFS)上的內容。3個詞的論點:
"/bin/bash" "-c" "echo hi"
變成 4 個單詞,echo hi按空格分開:
/bin/bash -c echo hi
或者更顯眼,這樣你就可以看到:
/bin/bash -c 'echo' hi
來自man bash:
-c [...] If there are arguments after the command_string, the first argument is assigned to $0 [...]
hi分配給$0for bash,然后 bashecho不帶引數執行。
我怎樣才能避免這種情況?
使用引號。
我怎樣才能讓它們在沒有 eval 的情況下作業。
使用引號。
用 shellcheck 檢查你的腳本。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/517276.html
上一篇:Rustunix行程
下一篇:為什么`__vfprintf_internal`(`stdio.h`中的`printfn`)強制`$rbp`在我的x86-64機器上向前跳轉6313864位元組?
