2016-10-14 4 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 вашего' ... 'как тест (если это одно слово без значения для команды test , проверяя, пустое ли это слово, но с '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" ]) ]; 

Я добавил фигурные скобки, чтобы понять, что вы имеете в виду с помощью или.

Теперь вы можете объединить все матчи с регулярным выражением:

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 

Everytime код становится трудно читать (а также для длинного кода или повторяющиеся утверждения), следует рассмотреть возможность использования функции.
Следующая функция коротка, но трудно читать:

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" 

Перед тем, как принять код, вы должны сделать несколько тестов.
Я сделал несколько тестов с небольшой петлей (теперь все ответы вместе)

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

Некоторые из них, я уверен, являются непереносимыми, если они правильны, - например, вложенные операторы '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' или '' '' '' ', которые расположены внутри этого вложенного контекста. И используя '(...)' вместо '{...; } 'для группировки принимает нетривиальный хит эффективности. –

Смежные вопросы