傳遞包含空格和萬用字元的參數的問題
如果參數可能包含萬用字元和/或空格,如果這些參數是可選的,那麼我在傳遞參數時會遇到問題。由於這聽起來很抽象,讓我們舉一個小例子:下面的 shell 腳本
some_command.sh
需要 2 或 3 個參數。第一個參數應該是命令行開關,第二個參數是可選的,如果存在,必須是形式的命令行開關,--NAME=VALUE
最後一個參數是必需的,可以是任何東西:#!/bin/bash # This is file some_command.sh # Synopsis: # some_command.sh --switch1=val1 [--switch2=val2] arg echo "switch1: $1" shift if [[ "$1" == --*=* ]] then echo "switch2 ($1) detected" shift fi echo argument is ${1:?argument missing}
假設我通過以下方式
some_command.sh
從其他腳本呼叫caller.sh
:#!/bin/bash # This is file caller.sh if [[ ${1:-x} == x ]] then switch="--abc=long argument" else switch="" fi some_command.sh "--exclude=*~" "$switch" arg
注意引用。引號
--exclude
是必須的,因為萬用字元表達式不能被shell擴展,而引號"$switch"
是必須的,因為$switch
可能包含帶有空格的文本,並且參數不能在空格上被打斷。目的是如果我們執行
caller.sh x
,這應該導致some_command.sh "--exclude=*~" "--abc=long argument" arg
如果我們執行,比如說
caller.sh y
,這應該變成some_command.sh "--exclude=*~" arg
caller.sh
我在這裡提供的,不能正常工作,因為在後一種情況下,它會執行some_command.sh "--exclude*~" "" arg
這是不正確的。
我試圖在命令前加上
eval
. 雖然這可以解決 的問題$switch
,但它也會刪除 周圍的引號"--exclude"
,並且萬用字元將由 shell 評估。我想我可以繼續使用
eval
, 並且只使用額外級別的引用,即"\"--exclude*~\""
,但這是一個糟糕的解決方案。我想知道是否有人有更清潔的方法來做到這一點。如果您想知道我為什麼會提出這個問題:我在編寫呼叫的腳本時偶然發現了這個問題
zip
,因為這些腳本應該能夠處理文件名中的空格。順便說一句,如前所述,問題發生在
bash
andzsh
。我也對聰明的解決方案感興趣,這些解決方案只適用於其中一個 shell。
使用數組,因為它可以擴展為可變數量的參數:
#!/bin/bash # This is file caller.bash switch=() if [[ ${1-x} == x ]] then switch=("--abc=long argument") fi some_command.sh "--exclude=*~" "${switch[@]}" arg
或者您可以使用以下
${var+...}
語法:#!/bin/sh # This is file caller.sh unset switch if [ "${1-x}" = x ] then switch="--abc=long argument" fi some_command.sh "--exclude=*~" ${switch+"$switch"} arg
請注意,使用 zsh,您可以執行以下操作:
#!/bin/zsh switch= if [ "${1-x}" = x ] then switch="--abc=long argument" fi some_command.sh "--exclude=*~" $switch arg
zsh
不會在參數擴展時執行split+glob,但它會執行空刪除,這正是您想要的。