2014-09-05 224 views
1

我在寫這將傳遞命令行參數,參數

  1. 行爲不同基於傳遞的第一個參數一個bash腳本檢測內容(沒有概率到目前爲止)
  2. 通過其餘該參數的命令(沒有概率到目前爲止)
  3. 行爲不同,如果參數包含字符串

它看起來像:

現在
[[ "${1}" = "-h" || "${1}" = "--help" ]] && echo -e "somehelp" 
[[ "${1}" = "echo" ]] && echo ${*:2} 
[[ "${1}" = "emerge" ]] && emerge -uDN ${*:2} 
some-magic-here 

,如果我做

myscript emerge -a whatever whatever2 --option 

它將運行

emerge -uDN -a whatever whatever2 --option 

但是,如果認爲 「無所謂」 是包含*一個字符串,如

myscript emerge -uDN -a whatever/* whatever2 --option 

我想讓它運行

emerge -uDN -a $(eix -u --only-names whatever/*) whatever2 --option 

改爲。有小費嗎?

+0

這是不可能的,因爲Bash甚至在它傳遞到腳本之前展開'*'。除非你在引號中用''whatever/*「'寫出 – user123444555621 2014-09-05 01:18:51

+0

這是可能的,你只需引用你的輸入。即'myscript emerge -uDN -a'whatever/*'whatever2 --option'或者變成一團糟。 – 2014-09-05 05:19:50

回答

-1

這裏有一個線索:

#!/bin/sh 

x="bbbccc"  # Put different strings in here, and see what happens 

case "$x" in 
*\**) 
    echo "Yes" 
    ;; 
    *) 
    echo "No" 
    ;; 
esac 
0

你提到的命令行:

myscript emerge -uDN -a whatever/* whatever2 --option 

的唯一途徑myscript會看到它的參數列表中的*是如果沒有子目錄whatever下的電流目錄,或者它是一個空目錄(嚴格來說:如果它包含任何文件,名稱全部以.開頭),並且無論哪種情況,您都沒有設置shopt -s nullglob。如果這些條件不滿足,調用myscript的shell將相應地替換*(in),並且myscript將不會看到*。 (當然,如果你引用的論據 - "whatever/*"'whatever/*',然後myscript也會看到*元字符,不論nullglobwhatever子目錄的存在或不存在。)

目前尚不清楚是否*需求只有在遵循-a選項時才被替換,或者在任何論點中都應該被替換。我會假設所有的論點都需要被取代;如果它只是應該替換的-a之後的參數,那麼它並沒有很大的不同。

如果沒有代碼來處理whatever/*,命令看起來像:

[[ "${1}" = "emerge" ]] && exec emerge -uDN "${@:2}" || exit 1 

差異:

  1. exec是可選的,但保證了emerge命令後什麼都不會被執行(除非emerge命令無法找到,在這種情況下|| exit 1確保沒有其他執行)。

  2. 使用"[email protected]"來保存呈現給腳本的參數。沒有雙引號,[email protected]$*之間沒有區別。在雙引號內,"$*"會生成單個字符串,但"[email protected]"會生成傳遞給腳本的每個參數。 "${@:2}"表示法對第二個到最後一個參數執行此操作。

要爲任何參數處理*,我們需要檢測*。如果我們使用數組,這將是最簡單的。

數組arglist將包含要傳遞給emerge命令的參數。我們需要的參數迭代的腳本,檢查的*出場:

arglist=("-uDN") 
for arg in "${@:2}" 
do 
    case "$arg" in 
    (*\**) arglist+=($(eix -u --only-names "$arg"));; 
    (*) arglist+=("$arg");; 
    esac 
done 
exec emerge "${arglist[@]}" 
exit 1 

注意,這個假設eix將擴展元字符(*要準確),而不是依靠外殼這樣做。正如問題所假設的那樣,它還假設eix生成的名稱中沒有空格。如果有的話,$(…)表示法將在空格(或製表符或換行符...)處拆分名稱。

該代碼會得到更好的爲then條款的身體

if [[ "${1}" = "emerge" ]] 
then 
    … 
fi 

處理這將是比試圖擠壓所有的代碼成一條線(其可以做的更清晰,但沒有指出這樣做,許多人指出不這樣做)。

1

首先,如果您打算將*傳遞給腳本,則必須防止shell在命令行上進行擴展。最簡單的方法是將引用它:

myscript emerge -a 'whatever/*' whatever2 --option 

既然你已經在使用[[操作,注:以下是慶典只有的解決方案,並不能移植到SH。如果要判斷$ 3包含*你可以使用=~操作:

[[ "${1}" == "emerge" ]] && { 
    [[ "$3" =~ "*" ]] && \ 
     emerge -uDN $2 $(eix -u --only-names $3) ${*:4} || \ 
     emerge -uDN ${*:2} 
} 

您也可以重寫,如果邏輯變得有點悽慘的複合命令到嵌套if-else語句。試試看,如果您有任何問題,請告訴我。