2017-01-17 3 views
0

У меня есть цикл для анализа аргументов командной строки. Все работает нормально, если аргумент -d или -b имеет параметр. Но когда я передаю -d или -b без параметра, сценарий попадает в бесконечный цикл.Логика логического вывода Bash работает в бесконечный цикл

# Parse command line input 
while [ "$#" -gt 0 ]; do 
    case "$1" in 
    -d) DOMAIN="$2"; shift 2;; 
    -b) BITS="$2"; shift 2;; 
    *) die "unrecognized argument: $1" 
    esac 
done 

Как выбросить ошибку при пустом параметре?

+3

Если ваши аргументы просто однобуквенные, вы можете использовать ['getopts'] (https://www.gnu.org/software/bash/manual/bashref.html#index-getopts) вместо того, чтобы , –

+1

Один трюк, который будет работать, особенно если у вас есть некоторые опции флага (которые не принимают аргументы) - это 'shift' вместо' shift 2' внутри 'case', а другой' shift' после 'esac' и до' done'. Параметры флага не потребуют сдвига вообще. Поскольку он сдвигал бы один аргумент за раз, он бы избавился от блуждающего '-b' без аргумента, поэтому цикл завершится. Тем не менее, ответ 'getopts' является лучшим долгосрочным выбором. Специальные решения приобретают специальные ошибки - свидетельствуйте о своей проблеме с бесконечным циклом. –

ответ

2

Команда shift n ничего не делает, если вы попытаетесь сдвинуть больше, чем количество значений, присутствующих в списке. В этом причина бесконечного цикла в вашем коде.

Использование getopts - это правильная вещь, так как она дает вам большую гибкость. В противном случае, вы можете переписать ваш цикл таким образом:

#!/bin/bash 
# Parse command line input 
d_flag=0 
b_flag=0 
while [ "$#" -gt 0 ]; do 
    case "$1" in 
    -d) 
     d_flag=1 
     shift 
     [[ $1 == -* ]] && continue # argument to -d not given 
     DOMAIN=$1 
     shift 
     ;; 
    -b) 
     b_flag=1 
     shift 
     [[ $1 == -* ]] && continue # argument to -b not given 
     BITS=$1 
     shift 
     ;; 
    *) echo "unrecognized argument: $1"; exit 2;; 
    esac 
done 

if [[ $d_flag = 1 && -z $DOMAIN ]]; then 
    # handle error - option requires an argument 
fi 

if [[ $b_flag = 1 && -z $BITS ]]; then 
    # handle error - option requires an argument 
fi 
0

Так как кажется, вам всегда нужно два параметра можно изменить первую строку:

while [ "$#" -eq 2 ]; do 

В противном случае вы можете проверить значение $ 2 до войти петля вот так:

+0

Это будет работать только тогда, когда у нас есть все варианты, принимающие аргумент, и поэтому мы можем рассматривать их как пары. – codeforester

1

Сдвиг сбой из-за недостаточного количества аргументов.

Эта проблема, однако, будет очевидна, так как вы устанавливаете свою оболочку для отказа при всех ошибках (с set -e). Во многих случаях отладка во многих случаях значительно упрощается, избегая бесшумных сбоев и обеспечивает проверку дисциплины и ошибок. set -u вызывает ошибки при неудачных расширениях переменных, также очень полезно.