2014-11-05 2 views
1

Я хочу переменную, значение которой должно быть в уже определенном диапазоне.Значение переменной оболочки в предопределенном диапазоне

, например.

переменная DAY = $ 1

должны получить только значения пн, вт, ср, Таким образом, Пт, Сб, Вс.

если пользователь вводит что-то еще, он не принимает его.

Я знаю, что могу это сделать, определяя массив или обычно переменную, хранящую все дни, а затем проверяет переменную ДНЕ в цикле «за или время».

Но я хочу простейший путь без цикла.

Заранее спасибо.

ответ

2

Используйте расширенную поддержку Глоба, чтобы точно соответствовать один из списка вариантов.

range="Mon|Tue|Wed|Thu|Fri" 
read day 
if [[ $day = @($range) ]]; then 
    echo "$day is valid" 
else 
    echo "$day is not valid" 
fi 
+0

Это единственный безопасный ответ. Кроме того, это самый чистый и самый короткий. Спасибо, Чэпнер за хорошие ответы! –

+1

К моему удивлению, 'shopt -s extglob' на самом деле не нужен, даже в 3.2. Замечания о выпуске 4.1 указывают, что 'extglob' временно включается внутри' [[...]] '" для совместимости ", который, как представляется, намекает на то, что такие шаблоны всегда являются расширенными шаблонами, даже если они явно не документированы как таковые. (Что имеет смысл, вам не нужна совместимость шаблонов POSIX внутри конструкции, отличной от POSIX, и шаблоны соответствуют строкам, а не именам путей.) – chepner

+0

Ах да, вы правы! Вы можете отменить мое редактирование (извините за это). –

1

без использования цикла вы можете сделать что-то вроде этого:

EOL=$'\n' 
arr=(Mon Tue Wed Thus Fri Sat Sun) 
read -p 'Enter day value: ' day 
Tue 

[[ $(printf "$EOL%s$EOL" "${arr[@]}") == *"$EOL$day$EOL"* ]] && 
    echo "in range" || echo "not in range" 
in range 

read -p 'Enter day value: ' day 
ue We 
[[ $(printf "$EOL%s$EOL" "${arr[@]}") == *"$EOL$day$EOL"* ]] && 
    echo "in range" || echo "not in range" 
not in range 
+0

Спасибо, кажется, работает, но что для остальных условий. я имею в виду, когда введенное значение не находится в радиусе действия, и я хочу что-то сделать для этого случая. –

+0

Я думаю, я могу использовать [[-z $ day]] && echo "in range" || эхо "не в радиусе действия". Но у вас есть что-то лучше, чем это, PLZ предложить. –

+0

'[[-z $ day]]' будет проверять длину строки равным нулю, она не будет проверять, существует ли '$ day' в массиве' $ arr' – anubhava

0

Чтобы немного расширить ответ анубхава в:

arr=(Mon Tue Wed Thus Fri Sat Sun) 
read -p 'Enter day value: ' day 
case "${arr[@]}" in *"$day"*) echo "in range";; esac 

В основном, это строит массив, превращая его в строку, и делать сопоставление с образцом на нем.

В контексте выражения case нет никакой разницы между "${arr[@]}" и "${arr[*]}"; Я лично придерживаюсь *, что дает понять, что вы строите одну большую строку вместо списка отдельных.

С помощью этого определенного набора значений вам не нужно беспокоиться о перекрытии подстроки, но вышеуказанная проверка все еще слишком прощает. Например, если вы введете u, это будет считаться «в диапазоне». Возможно, это не то, что вы хотите.

Более точное испытание было бы что-то вроде этого:

case "${arr[*]}" in 
    "$day "*|*" $day "*|*" $day") echo "in range";; 
    *) echo "not in range";; 
esac 

Это все еще позволяет пользователю ввести несколько дней, как «Mon Tue» или аналогичный; простой способ исправить это в этом конкретном случае - изменить линию read от read day до read day _.

Образец "$day "* будет соответствовать в начале массива (так что если в этом случае они вводят Mon). Образец *" $day" будет соответствовать в конце массива (Fri), а шаблон *" $day "* будет соответствовать остальным. Ничего другого, кроме точной строки дня, не будет соответствовать.

Кроме того, здесь вы можете увидеть, как обрабатывать else случая - картина * матчи ничего, что уже не согласованное что-то еще, так что это эквивалент else в case.

+1

Не удается выполнить вход пользователя в Mon Tue. –

0

Нет необходимости в массиве.

read -r day 
case ' Mon Tue Wed Thu Fri Sat Sun ' in 
    *" $day "*) 
    echo "in range";; 
    *) echo "not in range";; 
esac 

Обратите внимание на пространства вокруг строковых выражений.

Если вам нужно быть строгим, вы должны отклонить «Вторник», которого это не делает. Для этого потребуется вторая обертка case, которая неуклюжая, но не совсем громоздкая.

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