我在 bash 陣列中存盤要執行的命令,例如:
declare -a cmd=("sudo" "dnf" "update")
"${cmd[@]}"
Last metadata expiration check: 0:24:45 ago on Fri 07 Jan 2022 03:35:34 PM EST.
Dependencies resolved.
Nothing to do.
Complete!
現在,假設我想重定向輸出以減少噪音。這有效:
"${cmd[@]}" &>/dev/null
但我更愿意使用命令陣列存盤重定向,以便可以像陣列中的任何其他命令一樣添加/洗掉它:
declare -a cmd=("sudo" "dnf" "update" "&>/dev/null")
"${cmd[@]}"
Last metadata expiration check: 0:29:14 ago on Fri 07 Jan 2022 03:35:34 PM EST.
No match for argument: &>/dev/null
輸出沒有被重定向,最終的陣列元素只是像普通引數一樣被傳遞。有什么方法可以完成這項作業(即明智地使用 eval)或更好的策略嗎?
XY 陳述句:我正在嘗試使用條件來使我的程式輸出靜默。我可以這樣做:
silent=true
cmd=("sudo" "dnf" "update")
if silent; then
"${cmd[@]}" &>/dev/null
else # Be noisy
"${cmd[@]}"
fi
這導致在我的程式程序中出現大量重復的代碼(每個除錯操作都需要多個命令執行行)。相反,我更喜歡將重定向附加到陣列,例如:
silent=true
cmd=("sudo" "dnf" "update")
$silent && cmd =("&>/dev/null")
"${cmd[@]}"
此策略適用于函式和引數,但不適用于重定向。雖然我可以將 --quiet 標志應用于某些程式來實作這一點,但在某些情況下,我想重定向 stderr、重定向到檔案等。
uj5u.com熱心網友回復:
如何預先考慮到陣列?
# provide a function that wraps the content
silence() { "$@" >/dev/null 2>&1; }
if [ "$silent" = true ]; then
cmd=( silence "${cmd[@]}" )
fi
"${cmd[@]}"
當然,您可以無條件地使用該包裝器并使其負責作業:
maybe_silence() {
if [ "$silent" = true ]; then
"$@" >/dev/null 2>&1
else
"$@"
fi
}
maybe_silence "${cmd[@]}"
如果您真的希望能夠支持任意重定向(和其他 shell 語法),那么擁有一個僅應用一個重定向并保持其他所有內容不變的包裝器是有意義的。
with_redirection() {
local redirections=$1 # first argument contains redirections to perform
shift || return # remove it from "$@"
local cmd # create a local variable to store our command
printf -v cmd '%q ' "$@" # generate a string that evals to our argument list
eval "$cmd $redirections" # run the string with the redirection following
}
...所以你可以運行:
cmd=( with_redirection '&>/dev/null' sudo dnf update )
"${cmd[@]}"
...and only&>/dev/null受到eval類似行為的影響,而其他內容則正常傳遞。你甚至可以嵌套這個:
testfunc() { echo "this is on stderr" >&2; }
cmd=( with_redirection '>out.txt' with_redirection '2>&1' testfunc
...你最終得到this is on stderrin out.txt(當然,你也可以運行with_redirection '>out.txt 2>&1' testfunc以獲得相同的效果)。
uj5u.com熱心網友回復:
動態靜默重定向
#!/usr/bin/env sh
cmd() {
silent=$1
if [ true = "$silent" ]
then out=/dev/null
else out=/dev/stdout
fi
sudo dnf update > "$out"
}
uj5u.com熱心網友回復:
如果要避免重復"${cmd[@]}"代碼,可以使用子shell:
(
[[ $silent == true ]] && exec &>/dev/null
exec "${cmd[@]}"
)
我建議使用execifcmd將始終是外部命令。
uj5u.com熱心網友回復:
您必須使用eval變數擴展來處理 shell 操作。
declare -a cmd=("sudo" "dnf" "update" "&>/dev/null")
eval "${cmd[@]}"
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/405832.html
標籤:
