Чтение онлайн

ЖАНРЫ

UNIX — универсальная среда программирования
Шрифт:

Таблица 4.1: Регулярные выражения

grep
и
egrep
(в порядке убывания приоритета)

Метасимволы

^
и
$
привязывают шаблон к началу (
^
) или концу (
$
) строки. Например,

$ grep From $MAIL

ищет строки, содержащие

From
в вашей почтовой посылке, но

$ grep '^From' $MAIL

выдает строки, начинающиеся с

From
, которые, вероятнее всего, будут заглавными строками сообщений. Метасимволы регулярных выражений пересекаются с метасимволами интерпретатора, поэтому
всегда имеет смысл заключать шаблоны команды
grep
в апострофы.

Команда

grep
допускает классы символов, подобные тем, что используются интерпретатором: так,
[a-z]
задает любую строчную букву. Но есть и различия — если класс символов команды
grep
начинается с символа слабого ударения то шаблон задает любой символ, кроме входящих в данный класс. Значит,
[^0-9]
задает любой символ, кроме цифры. Как и в интерпретаторе, обратная дробная черта экранирует символы
]
и
в классе символов, но команды
grep
и
ed
требуют, чтобы эти символы использовались там, где их значение недвусмысленно. Например, шаблон
[][-]
задает открывающую или закрывающую квадратную скобку либо знак минус.

Точка

'.'
эквивалентна
'?'
в интерпретаторе: она задает любой символ. (Точка, по всей видимости, есть символ, назначение которого различно для разных программ.) Ниже приводятся два примера:

$ ls -l | grep '^d'
Список имен вложенных каталогов

$ ls -l | grep '^.......rw'
Список файлов, доступных всем для чтения и записи

Символ

'^'
и семь точек задают любые семь символов в начале строки; в случае применения к выходному потоку команды
ls -l
задается любая строка права доступа.

Операция "повторитель" (

'*'
) применима в выражении к предваряющему ее символу или метасимволу (включая класс символов), и вместе они обозначают любое число вхождений символа или метасимвола. Например,
x*
задает последовательность букв
x
произвольной длины,
[a-zA-Z]*
— любую строку букв,
.*
— все до конца строки, а
.*x
— все до последнего символа
x
в строке включительно. Необходимо отметить несколько важных моментов, связанных с повторителем. Во-первых, повторитель действует только на один символ, поэтому
xy*
соответствует
x
, за которым идут
yy...
, но не последовательности типа
xyxyxy
. Во-вторых, любое число включает нуль, поэтому если вы хотите, чтобы символ присутствовал, в шаблоне его нужно повторить. Например, правильным выражением, задающим строку букв, является такое:
[a-zA-Z][a-zA-Z]*
(буква, за которой следует нуль или более букв). Регулярное выражение
.*
соответствует —
*
, т.е. метасимволу интерпретатора, используемому для имен файлов.

Ни одно регулярное выражение команды

grep
не соответствует символу перевода строки; выражения сопоставляются с каждой строкой в отдельности. Регулярные выражения делают команду
grep
простым языком программирования. Вспомните, что второе поле файла паролей содержит зашифрованный пароль. Приведенная ниже команда проводит поиск пользователей, не имеющих пароля:

$ grep '^[^:]*::' /etc/passwd

Шаблон расшифровывается так: начало строки, любое число символов, отличных от двоеточия, два двоеточия.

Команда

grep
— старейшая в семействе программ, к которому относятся команды
fgrep
и
egrep
. В основном их действие одинаково, но
fgrep
может одновременно искать несколько литеральных строк, тогда как
egrep
интерпретирует настоящие регулярные выражения, подобно
grep
, но с использованием операций "or" и скобок для группировки выражений, что будет объяснено ниже.

Обе команды,

fgrep
и
egrep
, имеют флаг
– f
для указания файла, из которого читается шаблон. В этом файле символы перевода строк разделяют шаблоны при параллельном поиске. Допустим, что некоторые слова вы пишете неправильно. В этом случае можно проверить документацию на наличие таких слов, поместив их в файл по одному на строке и воспользовавшись командой
fgrep
:

$ fgrep -f типичные_ошибки документ

Регулярные выражения, интерпретируемые

egrep
(они также приведены в табл. 4.1), — те же самые, что и в grep, но с небольшими добавлениями. Можно использовать скобки для группировки, поэтому
(xy)*
задает пустую строку или любую последовательность
xy
,
xyxy
,
xyxyxy
и т.д. Вертикальная черта
|
является операцией or (или);
today|tomorrow
соответствует
today
или
tomorrow
, как и
to(day|morrow)
. Наконец, в команде
egrep
есть еще две операции повторения:
+
и
?
. Шаблон
x+
задает один или более символов
x
, а шаблон
x?
— нуль или один символ
x
(но не более).

Команда

egrep
прекрасно подходит для игр, в которых нужно искать в словаре слова со специальными свойствами. Мы будем обращаться к словарю Вебстера (второе международное издание), хранящемуся в файле в виде списка слов по одному в строке без определений их значения. В вашей системе может быть небольшой словарь
/usr/dict/words
, предназначенный для проверки правописания; просмотрите его, чтобы выяснить формат. Ниже приведен шаблон, задающий слова английского языка, содержащие все пять гласных в алфавитном порядке:

$ cat alphvowels

^[^aeiou]*a[^aeiou]*e[^aeiou]*i[^aeiou]*o[^aeiou]*u[^aeiou]*$

$ egrep -f alphvowels /usr/dict/web2 | 3

abstemious abstemiously abstentions

achelious acheirous acleistous

affectious annelidous arsenious

arterious bacterious caesious

facetious facetiously fracedinous

majestious

$

В файле

alphvowels
шаблон не взят в кавычки. Если применяются кавычки для экранирования шаблона в команде
egrep
, интерпретатор защищает его от интерпретации командами, но кавычки убирает, и команда
egrep
никогда "не узнает" о них. Поскольку интерпретатор не заглядывает в файл, кавычки не нужны для защиты содержимого файла. Для этого примера мы могли бы использовать команду
grep
, но алгоритм
egrep
таков, что она осуществляет поиск намного быстрее в случае шаблонов с повторителями, особенно при просмотре больших файлов.

В другом примере требуется найти все английские слова, состоящие из шести или более букв, в которых буквы следуют в алфавитном порядке:

$ cat monotonic

^a?b?c?d?e?f?g?h?i?j?k?l?m?n?o?p?r?s?t?u?v?w?x?y?z?$

$ egrep -f monotonic /usr/dict/web2 | grep '......' | 5

abdest acfcnow adipsy agnosy almost

bedfist behint befcnow bijoux biopsy

chintz dehors dehort demos dimpsy

Поделиться с друзьями: