2016-10-14 61 views
0

我正在使用if語句在bash中有多個條件。IF語句的倍數和或條件

如何減少以下行語法。所以從設計的角度看它很好。

if [ "$1" != "-l" ] && [ "$1" != "-a" ] && [ "$1" != "-h" ] && [ "$1" != "" ] && [ "$1" = "-d" ] || [ "$1" = "-mv" ] || [ "$1" = "-dv" ] || [ "$1" = "-mr" ] || [ "$1" = "-dr" ]; 

由於

+0

也許使有效/無效值的列表,然後選擇[檢查,如果該列表確實/不包含'$ 1']( http://stackoverflow.com/questions/8063228/how-do-i-check-if-a-variable-exists-in-a-list-in-bash) –

+1

也許你想使用'getopt'命令來爲你解析命令行選項? –

+0

@ G.Sliepen,[最佳實踐方法](http://mywiki.wooledge.org/BashFAQ/035)不涉及'getopt'。 –

回答

0

可以創建2個陣列用於匹配和非匹配值,並檢查是否1元件$匹配任何元素陣列中或低於不喜歡的。

nonmatch_array=("-l" "-a" "-h" "") 
match_array=( "-d" "-mv" "-dv" "-mr" "-dr") 

if [ `echo ${match_array[@]} | grep "$1"` ] || ! [ `echo ${nonmatch_array[@]} | grep "$1"` ] ; then 
    echo "is in array" 
else 
    echo "is not in array" 
fi 

希望它能爲你工作。

+0

'grep -q'總是什麼都沒有發出,而''''''''''正在評估你的'...'的stdout作爲一個測試(如果它是一個對測試命令沒有意義的單詞,檢查這個單詞是否是空的;但是用'grep -q',它總是**空的)。 –

+0

@CharlesDuffy:我的壞,不知何故錯過了..更新了答案。感謝您的注意。 –

+0

這裏還有一些改進 - 使用'grep'非常慢;考慮重寫使用關聯數組來執行O(1)時間內的所有進程中的測試。 –

1

使用模式匹配。

if [[ $1 && $1 != -[lah] && $1 == [email protected](d|mv|dv|mr|dr) ]]; then 

@(...)是擴展模式,這應該是默認在最新版本的bash被識別內[[ ... ]]的一個例子。如果您的版本不是最近的版本,請將shopt -s extglob添加到腳本的開頭。


事實上,你可以刪除$1 && $1 != -[lah],因爲它的真理會通過的$1 == [email protected](...)真相暗示。

if [[ $1 == [email protected](d|mv|dv|mr|dr) ]]; then 

你也可以只使用一個符合POSIX標準的case聲明:

case $1 of 
-d|-mv|-dv|-mr|-dr) echo good option ;; 
*) echo bad option ;; 
esac 
0

首先儘量限制在1行代碼的長度。

if [ [ "$1" != "-l" ] 
    && [ "$1" != "-a" ] 
    && [ "$1" != "-h" ] 
    && [ -n "$1" ] 
    && ([ "$1" = "-d" ] 
    || [ "$1" = "-mv" ] 
    || [ "$1" = "-dv" ] 
    || [ "$1" = "-mr" ] 
    || [ "$1" = "-dr" ]) ]; 

我添加了大括號,以明確你的意思是or。現在

你可以用正則表達式將所有的比賽:

if [[ ! ("$a" =~ ^-(l|a|h|d|)$) 
     && "$a" =~ ^-(mv|dv|mr|dr)$ ]]; then 
     echo "Yes $a matches" 
    fi 

,但是考慮你要測試的。只有當它匹配-mv/-dv/-mr/-dr時,測試纔會成立,因此您無需測試選件lah

if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then 
     echo "Yes $a matches" 
    fi 

您可以使用一個變量,用於提取的選項:

options="d|mv|dv|mr|dr" 
    if [[ "$a" =~ ^-(${options})$ ]]; then 
     echo "Yes $a matches" 
    fi 

每次代碼變得難以閱讀(也爲長碼或重複的語句),你應該考慮使用功能。
下一個函數是短暫的,但很難閱讀:

options="d|mv|dv|mr|dr" 
function checkoption1 { 
    [[ "$a" =~ ^-(${options})$ ]] 
} 
checkoption1 "$a" && 
    echo "Yes $a matches" 

我會選擇一個稍微更詳細的功能。我將包含您的原始測試lah以顯示可能性。

# checkoption return 0 for match, 
# returns 1 for forbidden option 
# returns 2 for undefined option 
function checkoption2 { 
    case "$1" in 
     -d|-mv|-dv|-mr|-dr) return 0 ;; 
     -l|-a|-h|"") return 1;; 
     *) return 2;; 
    esac 
} 
checkoption2 "$a" && 
    echo "Yes $a matches" 

你應該在接受你的代碼之前做一些testruns。
我已經取得了一些測試用小環(現在所有的答案在一起)

function checkoption1 { 
    [[ "$a" =~ ^-(${options})$ ]] 
} 

# checkoption return 0 for match, 
# returns 1 for forbidden option 
# returns 2 for undefined option 
function checkoption2 { 
    case "$1" in 
     -d|-mv|-dv|-mr|-dr) return 0 ;; 
     -l|-a|-h|"") return 1;; 
     *) return 2;; 
    esac 
} 

for a in -mv mv -mvx -ms -mr -dr; do 
     if [[ ! ("$a" =~ ^-(l|a|h|)$) 
      && "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then 
      echo "Yes $a matches" 
     fi 
     if [[ "$a" =~ ^-(d|mv|dv|mr|dr)$ ]]; then 
      echo "Yes $a matches" 
     fi 
     options="d|mv|dv|mr|dr" 
     if [[ "$a" =~ ^-(${options})$ ]]; then 
      echo "Yes $a matches" 
     fi 
     checkoption1 "$a" && 
      echo "Yes $a matches" 
     checkoption2 "$a" && 
      echo "Yes $a matches 2" 
done 
+0

如果這是正確的話,我相當肯定的一些是不可移植的 - 比如在嵌套上下文中嵌套'['s'或本地邏輯運算符(例如'&&')。使用'(...)'而不是'{...; }對於分組來說,正在遭受非平凡的效率影響。 –