Тест Bash: что делает «= ~»?

41
#!/bin/bash
INT=-5

if [[ "$INT" =~ ^-?[0-9]+$ ]]; then

echo "INT is an integer."

else

echo "INT is not an integer." >&2

exit 1

fi

Что делает ведущий ~в начальном регулярном выражении?

Рагнарок
источник
5
Вы читали руководство по bash? Что ты находишь неясным?
Икар
3
Ищите на справочной странице bash = ~
Джефф Шаллер

Ответы:

46

~Фактически является частью оператора , =~который выполняет регулярное выражение матч строки слева от нее к регулярному выражению справа.

[[ "string" =~ pattern ]]

Обратите внимание, что строка должна быть заключена в кавычки, а регулярное выражение не должно быть заключено в кавычки.

Аналогичный оператор используется в языке программирования Perl.

Под регулярными выражениями понимаются bashте же, которые GNU grepпонимает под -Eфлагом, т. Е. Расширенный набор регулярных выражений.


Несколько не по теме, но полезно знать:

При сопоставлении с регулярным выражением, содержащим группы захвата, часть строки, захваченная каждой группой, доступна в BASH_REMATCHмассиве. Нулевая / первая запись в этом массиве соответствует &в шаблоне sedзамены команды замещения (или $&в Perl), которая является битом строки, соответствующей шаблону, в то время как записи с индексом 1 и далее соответствуют \1, \2и т. Д. в sedшаблоне замены (или $1и $2т. д. в Perl), то есть биты, соответствующие каждой круглой скобке.

Пример:

string=$( date +%T )

if [[ "$string" =~ ^([0-9][0-9]):([0-9][0-9]):([0-9][0-9])$ ]]; then
  printf 'Got %s, %s and %s\n' \
    "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}"
fi

Это может вывести

Got 09, 19 and 14

если текущее время случается 09:19:14.

REMATCHБит BASH_REMATCHимени массива происходит от «регулярного выражения», то есть «RE-Match».


В bashоболочках, не похожих на Борн, можно также использовать exprограниченное сопоставление регулярных выражений (используя только базовые регулярные выражения).

Небольшой пример:

$ string="hello 123 world"
$ expr "$string" : ".*[^0-9]\([0-9][0-9]*\)"
123
Кусалананда
источник
2
Это то же самое, что grep -Eпонимается только в системах GNU и только при использовании в качестве шаблона переменной без кавычек [[ $var = $pattern ]](см. [[ 'a b' =~ a\sb ]]Vs p='a\sb'; [[ 'a b' =~ $p ]]). Также следует помнить, что цитирование оболочки влияет на значение операторов RE и что некоторые символы необходимо заключать в кавычки для маркировки оболочки, что может повлиять на обработку RE. [[ '\' =~ [\/] ]]возвращает ложь ksh93имеет еще худшие проблемы. См. zsh(Или bash 3.1) более разумный подход, в котором цитирование shell и RE четко разделено. [Встроенный в zshа yashтакже =~оператор.
Стефан
2
очень круто off-topic! +1 (
JJoao
@ StéphaneChazelas Как это "разумнее", что оба этого матча в Zsh ?: [[ "This is a fine mess." =~ T.........fin*es* ]]; [[ "This is a fine mess." =~ T.........fin\*es\* ]]. Или что цитируемый *тоже совпадает? [[ "This is a fine mess." =~ "T.........fin*es*" ]],
Соронтар
Это разумнее (IMO) в том смысле, что правила намного проще. Цитирование оболочки и выход из RE явно разделены. В [[ a =~ .* ]]или [[ a =~ '.*' ]]или [[ a =~ \.\* ]], тот же .*RE передается =~оператору. OTH, in bash, [[ '\' =~ [)] ]]возвращает ошибку, знаете ли вы, не пробуя ее, [[ '\' =~ [\)] ]]соответствует ли ? Как насчет [[ '\' =~ [\/] ]](это делает в ksh93). Как насчет c='a-z'; [[ a =~ ["$c"] ]](сравнить с =оператором)? Смотрите также: [[ '\' =~ [^]"."] ]]который возвращает ложное ... Обратите внимание , что вы можете сделать shopt -s compat31в , bashчтобы получить zshповедение.
Стефан
zsh/ bash -o compat31Поведение «s для [[ a =~ '.*' ]]также согласуется с [ a '=~' '.*' ](для [реализаций, поддержки =~) или expr a : '.*'. OTOH, это не согласуется с [[ a = '*' ]]vs [[ a = * ]](но в этом случае globs являются частью языка оболочки, а RE - нет).
Стефан
4

Вы должны прочитать справочные страницы Bash, в [[ expression ]]разделе.

An additional binary operator, =~, is available, with the same precedence as == and !=. When it is used, the string to the right of the operator is considered an extended regular expression and matched accordingly (as in regex(3)).

Короче говоря, =~оператор, так же, как ==и !=. Это не имеет никакого отношения к фактическому регулярному выражению в строке справа.

Sokel
источник
Можете ли вы найти примеры, демонстрирующие использование =~в реальной жизни ...?
Георгий
1
@ GeorgeVasiliou Я использую его довольно часто в сценариях, которые помещают вывод команды в переменную. Затем переменная проверяется на соответствие строковому шаблону. Это полезно, например, если вы хотите предпринять какое-либо действие, основанное на выводе какой-либо ошибки из этой команды.
Майкл Мартинес
@ Сокел Для некоторых «RTFM» легче сказать, чем сделать. ⋯ man [[ expresssion ]]и man [[ничего не вернуть. help [[возвращает полезную информацию - начиная [[с внутренней команды bash - но не говорит, =~использует ли базовый или расширенный синтаксис регулярных выражений. Quoted Текст, который вы цитировали, взят со страницы руководства bash . Я понимаю, что вы сказали «читать страницы руководства bash», но сначала я подумал, что вы хотите прочитать страницы руководства внутри bash. В любом случае, man bashвозвращает огромный файл длиной 4139 строк (72 страницы). Его можно искать нажатием /▒▒▒, которое принимает регулярное выражение, вкус которого, например =~, не указан.
Алекс Куинн