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
Поделиться с друзьями: