Как вы используете символ плюс с классом символов как часть регулярного выражения?

В cygwin это не возвращает совпадение:

$ echo "aaab" | grep '^[ab]+$'

Но это возвращает совпадение:

$ echo "aaab" | grep '^[ab][ab]*$'
aaab

Разве два выражения не идентичны? Есть ли способ выразить "один или несколько символов класса символов", не вводя класс символов дважды (как в примере секунд)?

По этой ссылке оба выражения должны быть одинаковыми, но, возможно, Regular-Expressions.info не охватывает bash в cygwin.

3 ответа

Решение

grep имеет несколько "режимов" сопоставления и по умолчанию использует только базовый набор, который не распознает несколько метасимволов, если они не экранированы. Вы можете поместить grep в расширенный режим или режим Perl, чтобы + оцениваться.

От man grep:

Matcher Selection
  -E, --extended-regexp
     Interpret PATTERN as an extended regular expression (ERE, see below).  (-E is specified by POSIX.)

  -P, --perl-regexp
     Interpret PATTERN as a Perl regular expression.  This is highly experimental and grep -P may warn of unimplemented features.


Basic vs Extended Regular Expressions
  In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \).

  Traditional egrep did not support the { meta-character, and some egrep implementations support \{ instead, so portable scripts should avoid { in grep -E patterns and should use [{] to match a literal {.

  GNU  grep -E attempts to support traditional usage by assuming that { is not special if it would be the start of an invalid interval specification.  For example, the command grep -E '{1' searches for the two-character string {1 instead of reporting a syntax
       error in the regular expression.  POSIX.2 allows this behavior as an extension, but portable scripts should avoid it.

Вы также можете использовать egrep вместо grep -E,

В основных регулярных выражениях метасимволы ?, +, {, |, (, а также ) потерять свое особое значение; вместо этого используйте версии с обратной косой чертой \?, \+, \{, \|, \(, а также \),

Так что используйте версию с обратной косой чертой:

$ echo aaab | grep '^[ab]\+$'
aaab

Или активируйте расширенный синтаксис:

$ echo aaab | egrep '^[ab]+$'
aaab

Маскирование обратной косой чертой или egrep как расширенный grep, псевдоним grep -e:

echo "aaab" | egrep '^[ab]+$'

AAAB

echo "aaab" | grep '^[ab]\+$'

AAAB

Другие вопросы по тегам