Shell-Script
如何在 POSIX shell 中執行具有未知數量參數的命令?
我想在目前目錄中搜尋多個單詞。為了做到這一點,我使用了類似的東西。
grep -e "word1" -e "word2" -R .
這工作正常。
更進一步,我創建了一個字典文件,其中包含換行符上的每個單詞,我想
grep
用這個字典創建命令。例如我有這個字典文件
one two three more
我想創建這個命令
grep -e "one" -e "two" -e "three" -e "more" -R .
我知道它可以用這樣的
bash
數組來完成:pattern=() while IFS= read -r line; do pattern+=("-e" "$line") done < "$dictionary" grep "${pattern[@]}" -R .
但是這怎麼能用僅 POSIX 的 shell 來完成呢?
我知道我可以創建一個作為
grep
命令的字元串並使用 執行它eval
,但是由於字典文件可以是任何東西,這對我來說聽起來不安全。
- 有沒有解決辦法
eval
?- 有沒有“安全”的解決方案
eval
?
POSIX shell 有一個數組:位置參數(
$1
,$2
, …),作為 共同訪問"$@"
,並使用set --
內置函式進行設置。更準確地說,目前呼叫堆棧上的每個函式實例都有一個數組,但在任何時候都只能訪問目前函式(或腳本,如果在任何函式之外)的位置參數數組。因此,如果您想使用此數組但不破壞腳本的參數,請在函式中工作。正如sml 已經指出的那樣,您使用 grep 的特定案例更簡單地通過使用
-F
grep 選項使其在每個文件行讀取一個模式來解決。但是,對於沒有類似grep -F
.set -- -a -b while IFS= read -r line; do set -- -e "$line" done < "$dictionary" mycommand "$@" more stuff
這呼叫
mycommand -a -b line1 line2 … more stuff
.如果您需要處理多個文件名列表(或具有任意內容的其他字元串),您可以明智地使用
eval
並非常小心地引用。很難獲得報價。下面的函式有兩個參數:一個變數名和一個字元串;它將字元串的引號形式附加到變數中。帶引號的形式是單引號文字,帶有適當轉義的單引號,適用於 shell 解析。append_to_quoted_list () { set -- "$1" "$(printf %s. "$2" | sed "s/'/'\\\\''/")" eval "$1=\"\${$1} '${2%?}'\"" }
這是一個範例用法,用於同時建構兩個列表。它
$command1
使用作為參數傳遞給-e
選項的行進行呼叫,然後$command2
使用作為--foo=…
選項傳遞的行。list1= list2= append_to_quoted_list list1 "$command1" append_to_quoted_list list1 "$command2" while IFS= read -r line; do append_to_quoted_list list1 -e append_to_quoted_list list1 "$line" append_to_quoted_list list2 "--foo=$line" done < "$dictionary" eval "$list1; $list2"
grep
您不想使用提供的或-f
開關-F
嗎grep
?從grep
手冊頁:-F, --fixed-strings Interpret PATTERN as a list of fixed strings, separated by newlines, any of which is to be matched. (-F is specified by POSIX.) -f FILE, --file=FILE Obtain patterns from FILE, one per line. The empty file contains zero patterns, and therefore matches nothing. (-f is specified by POSIX.)
例子
$ grep -F somefile.txt -R .