эквивалентность раскрытия скобок в bash [[ составная команда (оператор теста)

Я хочу, чтобы foo() соответствовал расширенному регулярному выражению или подобно раскрытие скобок.

Решение на основе egrep:

foo() 
{
  egrep -sq "$2" <<< "$1" && echo "string '$1' matches pattern '$2'"
}

$ foo bar '.*r'
string 'bar' matches pattern '*r'
$ foo bar '.*r|.*s'
string 'bar' matches pattern '*r|*s'

Но я также хочу 100% bash решение. Моя попытка:

foo() 
{
  [[ "$1" = $2 ]] && echo "string '$1' matches pattern '$2'"
}

Базовый шаблон в порядке:

$ foo bar '*r'
string 'bar' matches pattern '*r'

Но какое форматирование следует использовать для обнаружения чередования? / расширенный шаблон?

$ foo bar '*(r|s)'
$ foo bar '*\(r|s\)'
$ foo bar '*\(r\|s\)'
$ foo bar '*\{r,s\}'
$ foo bar '*{r,s}'

Кроме того, bash справочная страница говорит:

[[ выражение ]]
Разбиение на слова и раскрытие пути не выполняются для слов между [[ и ]]; Выполняется расширение с помощью тильды, расширение параметров и переменных, арифметическое расширение, подстановка команд, подстановка процессов и удаление кавычек.

  1. Есть ли способ использовать расширенное регулярное выражение/шаблон в операторе [[ ]]?
  2. Как бы вы реализовали такую ​​функцию?

person oHo    schedule 18.09.2013    source источник
comment
Ни один из показанных вами примеров, начинающихся с *, не является допустимым регулярным выражением.   -  person chepner    schedule 18.09.2013
comment
Ой вы правы! Хороший вопрос @chepner. Я думал, что шаблон был подмножеством регулярного выражения! Я исправил свой вопрос, добавив информационные/образовательные ссылки. Спасибо за вашу бдительность. Ваше здоровье ;-)   -  person oHo    schedule 18.09.2013


Ответы (2)


Вам нужно использовать оператор =~.

От man bash:

Доступен дополнительный бинарный оператор =~ с таким же приоритетом, как == и !=. Когда он используется, строка справа от оператора считается расширенным регулярным выражением и сопоставляется соответствующим образом.

Попробуй это:

foo() 
{
  [[ "$1" =~ $2 ]] && echo "string '$1' matches pattern '$2'"
}

Также обратите внимание, что * является подстановочным знаком (и подвергается «сопоставлению с образцом»), а .* является регулярным выражением.

Измените свой пример на:

$ foo bar '.*(r|s)'
string 'bar' matches pattern '.*(r|s)'
person dogbane    schedule 18.09.2013
comment
Это не правильно. =~ не проверяет соответствие шаблону, он проверяет, содержит ли эта строка строку, соответствующую шаблону. Таким образом, использование регулярного выражения .*(r|s) должно возвращать true для строки asshole. Вместо этого используйте ^pattern$ для полного соответствия - person Aleks-Daniel Jakimenko-A.; 19.09.2013

Вы имеете в виду это?

[[ 'bar' == *[rs] ]] && echo yes || echo no # this is simple globbing

Или с помощью extglobs:

shopt -s extglob
[[ 'bar' == @(*r|*s) ]] && echo yes || echo no

Для получения дополнительной информации вы можете прочитать страницу bash-хакеров о сопоставлении с образцом.

person Aleks-Daniel Jakimenko-A.    schedule 18.09.2013