[英]Pass command line arguments and command line argument
我希望我的腳本像這樣被調用:
./script -f "-a -b "foo bar"" baz
其中-a -b "foo bar"
是傳遞給由我的腳本內部執行的命令(例如grep
)的命令行參數。
這里的問題當然涉及到引用:天真的方法(將命令行參數擴展為script
)將foo
和bar
視為單獨的參數,這當然是不希望的。
做到這一點的最佳方法是什么?
沒有真正好的方法可以做到這一點,只有解決方法。 幾乎所有常見的解決方案都涉及將單個參數作為單個參數傳遞,因為另一種選擇-將一個參數列表作為單個參數傳遞-使您每次想要傳遞一個甚至稍微復雜的參數時,都可以繞過大火。會變成事實,這很常見;您的示例只是您將要陷入的元引號混亂的開始。有關更多見解,請參閱Bash FAQ條目 。
可能最常見的解決方案是將要傳遞的參數放在參數列表的末尾。 這意味着您需要知道實際用於腳本的參數的末尾,這或多或少意味着存在固定數量的位置參數。 通常,固定數字為1。該策略的一個例子是任何腳本解釋器( bash
本身, python
等)都很好地采用了一個唯一的位置參數,即腳本名稱。 那將使您調用:
./script baz -a -b "foo bar"
這並不總是很方便。 例如, find
命令具有-exec
選項,其后跟以下參數中的實際命令。 要做到這一點,您必須知道將單詞傳遞到何處。 find
通過使用特定的定界符參數來解決該問題:單個分號。 (這是一個任意選擇,但作為腳本參數很少見,因此通常可以解決。)在這種情況下,您的調用將類似於:
./script -f -a -b "foo bar" \; baz
的;
顯然,需要用引號引起來,因為否則它將終止命令,但這不是一個復雜的引號問題。
可以通過允許用戶顯式指定定界詞來擴展這一范圍:
./script --arguments=--end -a -b "foo bar" --end baz
這是一些類似find
的建議的示例代碼:
# Use an array to accumulate the arguments to be passed through
declare -a passthrough=()
while getopts f:xyz opt; do
case "$opt" in
f)
passthrough+=("$OPTARG")
while [[ ${!OPTIND} != ';' ]]; do
if ((OPTIND > $#)); then
echo "Unterminated -f argument" >>/dev/stderr
exit 1
fi
passthrough+=("${!OPTIND}")
((++OPTIND))
done
((++OPTIND))
;;
# Handle other options
esac
done
# Handle positional arguments
# Use the passthrough arguments
grep "${passthrough[@]}" # Other grep arguments
我發現了一種更短的方法,可以將腳本參數作為參數傳遞給命令,並且沒有任何限制:應評估命令。
在您的問題中,以下script
將完成您想要的
#!/bin/bash
# Do whatever you want ...
# Just claim that 2nd quoted argument of script should be passed as
# a set of parameters of grep
eval grep $2
然后,您可以使用包含空格的參數調用此script
,以將其傳遞給grep
./script -f "-a -b \"foo bar\"" baz
要么
./script -f '-a -b "foo bar"' baz
瞧! 將使用正確的參數調用grep
grep -a -b "foo bar"
例如,致電
./script -f '-i "system message" /etc/passwd' baz
然后得到正確的輸出
dbus:x:81:81:System message bus:/:/sbin/nologin
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.