Shell-Script

如何在 POSIX shell 中執行具有未知數量參數的命令?

  • September 27, 2014

我想在目前目錄中搜尋多個單詞。為了做到這一點,我使用了類似的東西。

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 的特定案例更簡單地通過使用-Fgrep 選項使其在每個文件行讀取一個模式來解決。但是,對於沒有類似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開關-Fgrep?從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 .

引用自:https://unix.stackexchange.com/questions/157644