Bash
將 $@ 分配給 shell 函式中的另一個變數
我正在製作一個
gc
可以區分 git commit/checkout 的智能別名。如果
gc
在沒有任何參數或使用-a
,-m
參數的情況下呼叫,則執行 git commit。否則,執行 git checkout (如果有一個b
帶有附加參數的標誌)。如果呼叫 gc 的任何其他變體,我寧願它拋出錯誤而不是做一些意想不到的事情。到目前為止,這是我的 shell 函式。
gc() { args=$@ commit=false checkout=false # Check flags while getopts ":am:b" opt; do case $opt in a|m) commit=true ;; b) checkout=true ;; \?) echo "Unknown flags passed." return 1 ;; esac done shift "$((OPTIND-1))" # Check number of arguments if [[ "$#" == 0 ]]; then commit=true elif [[ "$#" == 1 ]]; then checkout=true else echo "Too many arguments" return 1 fi # Finally run respective command if [[ $commit == true && $checkout == true ]]; then echo "Unable to ascertain which operation you would like to perform." return 1 elif [[ $commit == true ]]; then git commit "$args" elif [[ $checkout == true ]]; then git checkout "$args" else echo "Undefined behavior" return 1 fi }
但是,這不能正常工作。經過一番試驗,我發現分配
$@
給另一個變數是根本原因,但我無法理解為什麼以及到底出了什麼問題。另外,由於我是第一次編寫 shell 函式,因此請突出顯示我所犯的任何錯誤。
$@
是一個數組,將其分配給一個數組:args=("$@")
然後將其用作數組:
elif [[ $commit == true ]]; then git commit "${args[@]}" elif [[ $checkout == true ]]; then git checkout "${args[@]}" else
目前程式碼中發生的情況是,所有單獨的參數都儲存為單個字元串。所以如果你打電話:
bc -a "foo bar"
這被分配
args
為:args='-a foo bar'
然後代替執行:
git commit -a "foo bar"
你得到:
git commit '-a foo bar'
由於另一個答案不是 POSIX,所以這裡有一個替代方案。如果你想暫時粉碎位置參數,你可以這樣做:
s1=$(printf '%s\n' "$@")
然後當您準備好恢復時,請執行以下操作:
IFS=' ' set -- $s1
請注意,這假定參數不包含換行符。如果是這樣,則需要使用不同的分隔符。
旁注:如果您注意到,最後一行包含一個未引用的變數。這是可以接受不帶引號的變數的少數情況之一(在我看來,這是唯一的情況):使用者已明確設置
IFS
. 使用者基本上說“是的,我知道我在做什麼,請繼續”。