if [ foo = bar -o foo = car -o foo = jar -o foo = foo ]
then
echo yes
fi
Чтобы держать вещи более организованными, я хотел бы попытаться сопоставить их со списком, таким как
if [ foo = {bar,car,jar,foo} ] ; then
Очевидно, что метод расширения фигурных скобок не сработал, иначе я бы не стал не быть здесь! Но я хотел бы знать, возможно ли что-то подобное вообще.
Я предлагаю использовать выбирающую структуру. Что-то как:
case $foo in
foo|car|bar|jar) echo yes ;;
*) ;;
esac
, Если Вам нравится, можно добавить команду между *)
и ;;
, чтобы быть выполненными, когда $foo
не соответствует foo
, car
, bar
, или jar
. Например, Вы могли распечатать сообщение с echo 'wrong input'
или что-то как этот.
Еще короче:
[[ $foo =~ ^([bcj]ar|foo)$ ]] && echo yes
Этот путь $foo
подобран против regex, или запускающегося с b
, c
или j
сопровождаемый ar
или соответствующего точно foo
.
Это использует &&
оператор как короткое замыкание для выполнения echo yes
, только если [[ $foo =~ ^([bcj]ar|foo)$ ]]
выражение оценивает к истинному.
, Если это слишком компактно, чтобы быть считанными легко, можно все еще использовать полное, если конструкция, которая делает точно то же, но более читаема:
if [[ $foo =~ ^([bcj]ar|foo)$ ]]
then
echo yes
fi
Если Вы действительно записали свое выражение с [ foo = bar -o foo = car -o foo = jar -o foo = foo ]
, затем это, возможно, было упрощено до:
echo yes
Этот тест всегда верен потому что foo = foo
всегда верно, который в свою очередь является потому что литеральная строка foo
всегда то же как само.
Хотя Вы разъяснили, что этот синтаксис не появился в коде, который Вы действительно использовали, я сохранил этот вводный раздел, поскольку это - частая ошибка сделать так, особенно среди новичков. Попытка проверить значение foo
этот путь не работает ни в какой оболочке стиля Границы - для исследования значения переменной с [
, необходимо выполнить расширение параметра с $
(см. ниже). Этот конкретный аспект проблемы не является определенным для оболочки; например, вот тест в 7 оболочках стиля Границы.
Возможно, вместо этого Вы означали проверять значение foo
переменная (т.е. ее содержание, а не ее имя) против тех строк. В этом случае Ваш исходный код стал бы как:
if [ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ]; then
echo yes
fi
Это может быть сокращено немного с коротким замыканием &&
оператор:
[ "$foo" = bar -o "$foo" = car -o "$foo" = jar -o "$foo" = foo ] && echo yes
Но это является еще длиннее и более сложным и повторяющимся, чем Вы, вероятно, предпочитаете. Так, хождение дальше...
Можно использовать [[
встроенный оператор соответствия регулярного выражения средства:
[[ $foo =~ ^(bar|car|jar|foo)$ ]] && echo yes
При использовании case
вероятно, наиболее распространенный способ, [[
с =~
:
case
(см. ниже),[[
, который работает во многом как проверяемое выражение.Таким образом, Вы могли бы предпочесть это. Это - метод, который я, вероятно, использовал бы, чтобы сделать это в ударе.
Если Вы хотели сделать что-то как этот кроме использования соответствия grep
вместо [[
с =~
, это подобно:
grep -Eq '^(bar|car|jar|foo)$' <<< "$foo" && echo yes
Или это:
grep -Fqe{bar,car,jar,foo} <<< "$foo" && echo yes
case
Как Serg говорит, может быть упрощен с помощью case
вместо if
и [
. Это - классик и вероятно наиболее распространенный способ.
Метод в ответе Serg работает отлично, но для конкретного кода Вы осуществляете рефакторинг, мы можем записать что-то более простое, при помощи только одного шаблона для case
. Нет никакой потребности иметь вместилище *)
соответствие в конце. Если строка не соответствует ни одному из шаблонов, управление просто проваливается, конструкция случая и никакие команды выполняются, который эквивалентен Вашему if
создайте без else
.
case $foo in bar|car|jar|foo) echo yes;; esac
Это делает это коротким и достаточно простым легко соответствовать - и быть читаемым - на одной строке (который, кажется, то, что Вы ищете). Этот метод является также портативным к оболочкам стиля Границы кроме удара.