Достаточно простой пример, в котором мы передаем по конвейеру вывод команды echo на ввод grep и видим результат. Если обнаруживается совпадение, мы видим вывод; если совпадение отсутствует, ничего не выводится.
Теперь добавим чередование, обозначаемое метасимволом вертикальной черты:
[me@linuxbox ~]$ echo "AAA" | grep -E 'AAA|BBB'
AAA
[me@linuxbox ~]$ echo "BBB" | grep -E 'AAA|BBB'
BBB
[me@linuxbox ~]$ echo "CCC" | grep -E 'AAA|BBB'
[me@linuxbox ~]$
Здесь мы видим регулярное выражение 'AAA|BBB', которое означает «совпадение со строкой AAA или со строкой BBB». Так как это расширенная особенность, мы добавили в команду grep параметр -E (вместо этого можно было бы использовать программу egrep) и заключили регулярное выражение в кавычки, чтобы предотвратить интерпретацию командной оболочкой символа вертикальной черты как оператора конвейера. В чередовании может быть более двух вариантов:
[me@linuxbox ~]$ echo "AAA" | grep -E 'AAA|BBB|CCC'
AAA
Для объединения с другими элементами регулярного выражения чередование можно заключать в круглые скобки :
[me@linuxbox ~]$ grep -Eh '^(bz|gz|zip)' dirlist*.txt
Этому выражению будут соответствовать имена файлов из наших списков, начинающиеся с bz, gz или zip. Если отбросить круглые скобки, смысл регулярного выражения изменится, и ему будут соответствовать имена, начинающиеся с bz или содержащие gz или zip:
[me@linuxbox ~]$ grep -Eh '^bz|gz|zip' dirlist*.txt
Квантификаторы
Расширенные регулярные выражения поддерживают несколько способов определения числа совпадений с элементом.
? — совпадение с элементом ноль или один раз
Этот квантификатор фактически означает: «совпадение с предыдущим элементом не обязательно». Представьте, что нужно проверить допустимость номера телефона, и предполагается, что номер допустим, если представлен в одной из двух форм:
^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$
В этом выражении за круглыми скобками следуют знаки вопроса, указывающие, что скобки могут либо отсутствовать, либо присутствовать один раз. И снова, поскольку круглые скобки считаются метасимволами (в ERE), мы экранировали их обратными слешами, чтобы они интерпретировались как литералы.
Попробуем применить это выражение:
[me@linuxbox ~]$ echo "(555) 123-4567" | grep -E '^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]$'
(555) 123-4567
[me@linuxbox ~]$ echo "555 123-4567" | grep -E '^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$'
555 123-4567
[me@linuxbox ~]$ echo "AAA 123-4567" | grep -E '^\(?[0-9][0-9][0-9]\)? [0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]$'
[me@linuxbox ~]$
Здесь регулярному выражению соответствуют обе формы записи номера телефона, но ему не соответствует номер, содержащий нецифровые символы.
* — совпадение с элементом ноль или более раз
Подобно метасимволу ?, звездочка (*) обозначает необязательный элемент; однако, в отличие от знака вопроса (?), этот элемент может встречаться любое число раз, а не только единожды. Представьте, что нам нужно проверить, является ли строка предложением. Чтобы удовлетворять нашим требованиям строка должна начинаться с большой буквы, содержать любое число букв верхнего и нижнего регистра и пробелов и заканчиваться точкой. Для поиска совпадений с этим (очень приблизительным) определением предложения воспользуемся следующим регулярным выражением:
[[:upper:]][[:upper:][:lower:] ]*\.
Выражение состоит из трех элементов: выражение в квадратных скобках с классом символов [:upper:], выражение в квадратных скобках с двумя классами символов, [:upper:] и [:lower:], и пробелом, и точка, экранированная обратным слешем. Второй элемент сопровождается метасимволом *, поэтому в нашем предложении ему может соответствовать любое число букв верхнего и нижнего регистра и пробелов, следующих за первой буквой верхнего регистра:
[me@linuxbox ~]$ echo "This works." | grep -E '[[:upper:]][[:upper:][:lower:] ]*\.'
This works.
[me@linuxbox ~]$ echo "This Works." | grep -E '[[:upper:]][[:upper:][:lower:] ]*\.'
This Works.
[me@linuxbox ~]$ echo "this does not" | grep -E '[[:upper:]][[:upper:][:lower:] ]*\.'
[me@linuxbox ~]$