Bash

Bash函式/腳本參數完全複製到變數中

  • September 19, 2022

如何將 Bash 函式/腳本參數完全複製到變數中,因為'(可能還有其他字元)不能保留在變數中?

例如

m() {
v="$@"
echo "$v"
}

$ m let it be 'foo' bar
let it be foo bar

感謝真誠的幫助,謝謝。

這裡要注意的是,當你執行例如

m let it be 'foo bar'

該程序m沒有得到整個命令行,但shell首先解析命令行,處理引號、變數擴展和類似的東西。該命令的最終結果更像是一個單獨的字元串數組,在本例中為 [ let, it, be, foo bar]。

同樣,在

f="James Matthew"
l="Bond"
m "$l, $f $l"

m只會看到 [ Bond, James Matthew Bond],並且不知道所涉及的變數和引號。

這意味著正常程序無法訪問原始輸入行。


在Any shell 中,在沒有轉義或引用的情況下關閉擴展的情況下,使用 pre-exec 處理程序的 zsh 有解決方法?和zsh: alias or shell function 只回顯它的命令行,包括 shell control characters,但我想我沒見過 Bash 的。

最接近你的是DEBUG陷阱,它看到在擴展、報價處理和重定向之前要執行的命令。但它並不完整,因為它一次只能看到一個簡單的命令。評論會在看到它們之前被刪除,並且未引用的;, &, |, &&, ||,()(至少)仍將被解析。

無論如何,我們可以嘗試:

#!/bin/bash

shopt -s extdebug

handle_@() {
   local re='[[:space:]]*@ ([^[:space:]]+)[[:space:]]+(.*)'
   if [[ $BASH_COMMAND =~ $re ]]; then
       "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"
       return 1
   fi
}
m() {
   printf "<%s>\n" "$1"
}

trap handle_@ DEBUG

@ m 'foo bar' doo "$var" > /dev/null
@ m what about this?; date
@ m or some (parentheses)?

該腳本使用DEBUG陷阱檢測以 開頭的命令@ ,將下一個以空格分隔的“單詞”作為要執行的命令,並將其餘的作為單個參數傳遞給它。從陷阱處理程序返回1告訴 shell 實際上不執行命令(使用extdebugset。)

輸出是這樣的,顯示date分號之後的執行,並且括號破壞了語法:

<'foo bar' doo "$var" > /dev/null>
<what about this?>
Sun Sep 18 18:39:38 EEST 2022
debugprint.sh: line 20: syntax error near unexpected token `('
debugprint.sh: line 20: `@ m or some (parentheses)?'

這是一組相當隨意的限制,我不能保證腳本也沒有其他問題。


一般來說,如果您計劃將此用於某種生產用途,我建議重新考慮程序的結構並通過文件或例如 here-doc 獲取字元串,具體取決於您在做什麼。

一個 here-doc 使得輸入原始字元串變得相對容易,儘管它通過命令的stdin

m() {
   m=$(cat) 
   printf "<%s>\n" "$m"
}
m <<'EOF'
Say "$hello" to my 'little friend'
EOF

那列印

<Say "$hello" to my 'little friend'>

使用帶引號的 here-doc 分隔符字元串 (in <<'EOF'),您可以在其中放置任意文本和字元,而無需擔心引號。(當然,除了分隔符字元串本身,但您可以使用隨機生成的字元串來代替EOF.)

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