Я пытаюсь использовать переменную, состоящую из разных строк, разделенных с помощью |
в качестве case
проверки операторов. Например:
string="\"foo\"|\"bar\""
read choice
case $choice in
$string)
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Я хочу иметь возможность набрать foo
или bar
выполнить первую часть case
заявления. Впрочем, и то, foo
и другое bar
меня возьмут
$ foo.sh
foo
Bad choice!
$ foo.sh
bar
Bad choice!
Использование "$string"
вместо $string
не имеет значения. Ни один не использует string="foo|bar"
.
Я знаю, что могу сделать это так:
case $choice in
"foo"|"bar")
echo "You chose $choice";;
*)
echo "Bad choice!";;
esac
Я могу думать о различных обходных путях, но я хотел бы знать, возможно ли использовать переменную в качестве case
условия в bash. Возможно ли это, и если да, то как?
bash
shell-script
case
Тердон
источник
источник
eval
, исключая $ choice, parens, звездочку, точку с запятой и символы новой строки. Ужасно, но это "работает".read
бит остановил меня. по моему мнению, проверка правильности ввода данных пользователем, что и выглядит, чтоcase
шаблоны не должны быть в верхней части списка оценки, а должны быть сокращены до*
шаблона по умолчанию, так что единственные результаты, которые там достигаются, гарантированно приемлемы. Тем не менее, поскольку проблема заключается в порядке разбора / расширения, тогда может потребоваться вторая оценка.Ответы:
Руководство по bash гласит:
Нет «Расширение пути»
Таким образом: шаблон НЕ раскрывается с «расширением пути».
Следовательно: шаблон НЕ может содержать «|» внутри. Только: два шаблона могут быть объединены с "|".
Это работает:
Использование «Extended Globbing»
Однако
word
это соответствуетpattern
правилам «Расширение пути».А «Extended Globbing» здесь , здесь и здесь позволяет использовать чередующиеся («|») шаблоны.
Это также работает:
Строковый контент
Следующий тестовый скрипт показывает, что шаблон, который соответствует всем строкам, которые содержат
foo
илиbar
где-'*$(foo|bar)*'
либо, или две переменные$s1=*foo*
и$s2=*bar*
Скрипт тестирования:
источник
Вы можете использовать
extglob
опцию:источник
@(foo|bar)
особенным по сравнению сfoo|bar
? Оба являются допустимыми шаблонами, которые работают одинаково при буквальном наборе.|
это не часть шаблонаfoo|bar
, это часть синтаксисаcase
оператора, позволяющая использовать несколько шаблонов в одном предложении.|
является частью расширенного шаблона, хотя.Вам нужны две переменные,
case
потому что|
труба или анализируется перед расширением шаблонов.Шаблоны оболочки в переменных обрабатываются по-разному, когда они заключаются в кавычки или не заключаются в кавычки:
источник
Если вы хотите обходной путь, совместимый с тире, вы можете написать:
Объяснение: awk используется для разбиения «строки» и проверки каждой части отдельно. Если «choice» соответствует проверенной в данный момент части p [i], команда awk завершается строкой «exit» в строке 11. Для самого теста используется «case» оболочки (в вызове 'system') как спросил тердон. Это сохраняет возможность изменить предполагаемую тестовую «строку», например, на «foo * | bar», чтобы соответствовать также для «foooo» («шаблон поиска»), как позволяет «case» оболочки. Если вместо этого вы бы предпочли регулярные выражения, вы могли бы опустить системный вызов и вместо этого использовать awk "~" или "match".
источник