Bash
Shell 函式:作為參數的管道序列
我有一個 shell 函式(在 .bashrc 中),它創建一個臨時文件,執行參數(包括所有管道序列),將其重定向到一個臨時文件,然後在 VS Code 中打開它。
我呼叫 shell 函式為
Temp "ls | nl"
在下面的程式碼中,我試圖讓它工作。我用 IFS 將整個字元串分解為一個空格,將其儲存在一個數組中。現在我想執行整個管道序列並將最終的標準輸出重定向到臨時文件。我怎樣才能做到這一點。?我知道 for 循環在這裡不起作用。但我想列印整個數組。
Temp() { a="$(mktemp --suffix=.md "/tmp/$1-$(GetFilename "$2")-XXX")" IFS=' ' read -r -a Array <<< "$1" nArray=${#Array[@]} # Size of array for ((i=0; i<nArray; i=i+1)); do done #"${@}" > "$a" code -r "$a" }
在互動式終端會話中,以下工作:
cat <<EOF $(ls | nl) EOF
所以,我嘗試了 Heredoc,而不是函式內的 for 循環
cat > "$a" <<EOF $($1) EOF
但這會引起引號
|
,因此失敗了。如果我們可以以某種方式刪除引號,上述方法將起作用。
這也行不通
cat > "$a" <<EOF $(echo $1 | sed "s/'//g") EOF
如果您希望函式執行作為參數給出的 shell 命令,則需要
eval
在字元串上使用,例如列印FOO
:eval_arg() { eval "$1" } eval_arg "echo foo |tr a-z A-Z"
僅僅擴展
"$1"
是行不通的,因為像管道、引號和重定向這樣的 shell 語法在參數擴展之後不會被處理。將第一個參數拆分為數組或拆分$@
並不會真正改變這一點。因此,
$(ls | nl)
有一個逐字管道字元,它在 shell 中處理,但在 中$($1)
,值中的任何特殊字元$1
都不會被處理(除了分詞和 glob)。這裡沒有引用。至於最後一個範例,
$(echo $1 | sed "s/'//g")
拆分$1
on whitespace 的值(使用 default 進行單詞拆分IFS
),然後將單詞與空格 (echo
) 連接起來,將其作為輸入傳遞給sed
它,從而刪除那裡的任何單引號。因此:
$ set -- "'foo bar'" $ $(echo $1 | sed "s/'//g") foo bar
命令中的外引號
set
由 shell 處理,而內引號是值的一部分。請注意,justset -- 'foo bar'
不會導致$1
包含任何引號,此處唯一的引號將作為正常 shell 處理的一部分被刪除。