Прежде чем вы приступите к прочтению главы, создайте представленный ниже файл с именем data.f, содержащий информацию о заказах товаров. Структура записей этого файла такова:
1–й столбец — код города;
2–й столбец — код месяца, когда был сделан заказ;
3–й столбец — код заказа, включающий год, когда он был сделан;
4–й столбец — код товара;
5–й столбец — цена за единицу товара;
6–й столбец — код фирмы;
7–й столбец — количество заказанного товара.
$ cat : data .f
48 dec 3ВС1997 LPSX 68.00 LVX2A 138
483 sept 5AP1996 USP 65.00 LVX2C 189
47 oct 3ZL1998 LPSX 43.00 KVM9D 512
219 dec 2CC1999 CAD 23.00 PLV2C 68
484 nov 7PL1996 CAD 49.00 PLV2C 234
483 may 5PA1998 USP 37.00 KVM9D 644
216 sept 3ZL1998 USP 86.00 KVM9E 234
Разделителем полей является символ табуляции.
8.1. Команда grep
Общий формат команды grep таков:
grep [параметры] базовое_регулярное_выражение [файл]
В качестве регулярного выражения может быть указана обычная строка. Если не задан файл, текст берется из стандартного входного потока.
8.1.1. Употребление кавычек
Строку, которая задана в качестве регулярного выражения и состоит из нескольких слов, следует заключить в двойные кавычки. В противном случае первое слово строки будет воспринято как образец поиска, а все остальные слова будут считаться именами файлов. В итоге отобразится сообщение о том, что указанные файлы не найдены.
Если образец поиска состоит из какой‑нибудь системной переменной, например $PATH, рекомендуется тоже взять ее в двойные кавычки. Это связано с тем, что, прежде чем передавать аргументы команде grep, интерпретатор shell выполняет подстановку переменных, и команда grep получает значение переменной, которое может содержать пробелы. В этом случае будет выдано то же сообщение об ошибке, о котором говорилось в предыдущем абзаце.
Шаблон поиска должен быть заключен в одинарные кавычки, если в состав регулярного выражения входят метасимволы.
8.1.2. Параметры команды grep
Ниже перечислены основные параметры команды grep:
-c
Задает отображение только числового значения, указывающего, сколько строк соответствуют шаблону
-i
Дает указание игнорировать регистр символов
-h
Подавляет вывод имен файлов, включающих найденные строки (по умолчанию в выводе команды grep каждой строке предшествует имя файла, в котором она содержится)
-1
Задает отображение только имен файлов, содержащих найденные строки
-n
Задает нумерацию выводимых строк
-s
Подавляет вывод сообщений о несуществующих или нетекстовых файлах
-v
Задает отображение строк, не соответствующих шаблону
8.1.3. Поиск среди нескольких файлов
Если в текущем каталоге требуется найти последовательность символов "sort" во всех файлах с расширением doc, выполните такую команду:
$ grep sort *.doc
Следующая команда осуществляет поиск фразы "sort it" во всех файлах текущего каталога:
$ grep "sort it" *
8.1 4. Определение числа строк, в которых найдено совпадение
Опция -c позволяет узнать, сколько строк соответствуют заданному шаблону. Это может оказаться полезным в том случае, когда команда grep находит слишком много строк, и их лучше вывести в файл, а не на экран. Рассмотрим пример:
$ grep -с "48" data.f
4
Команда grep возвращает число 4. Это означает, что в файле data.f обнаружены 4 строки, содержащие последовательность символов "48". Следующая команда отображает эти строки:
$ grep "48" data.f
48 dec 3BC1997 LPSX 68.00 LVX2A 138
453 sept 5AP1996 USP 65.00 LVX2C 189
484 nov 7PL1996 CAD 49.00 PLV2C 234
4 83 may 5PA1998 USP 37.00 KVM9D 644
8.1.5. Вывод номеров строк
С помощью опции -n выводимые строки можно пронумеровать. В результате вы сможете с легкостью устанавливать, в какой позиции файла находится требуемая строка. Например:
$ grep -n "48" data.f
1: :48 dec 3BC1997 LPSX 68.00 LVX2A 138
2: :483 sept. 5AP1996 USP 65.00 LVX2C 189
5: :484 nov 7PL1996 CAD 49.00 PLV2C 234
6: :483 may 5PA1998 USP 37.00 KVM9D 644
Номера строк отображаются в первом столбце.
8.1.6. Поиск строк, не соответствующих шаблону
Благодаря опции -v можно отобрать те строки, которые не соответствуют шаблону. Следующая команда извлекает из файла data.f строки, не содержащие последовательность символов "48":
$ grep -v "48" data.f
47 oct 3ZL1998 LPSX 43.00 KVM9D 512
219 dec 2CC1999 CAD 23.00 PLV2C 68
216 sept 3ZL1998 USP 86.00 KVM9E 234
8.1.7. Поиск символов на границе слов
Вы, наверное, заметили, что при поиске строк, содержащих последовательность символов "48", были найдены строки заказов с кодом города не только 48, но также 483 и 484. Если необходимо найти заказ, у которого код города равен 48, добавьте в шаблон поиска символ табуляции:
$ grep "48<tab>" data.f
48 Dec 3BC1997 LPSX 68.00 LVX2A 138
Здесь запись <tab> означает нажатие клавиши [Tab].
Если не известно, какой пробельный символ является разделителем полей в файле, можно воспользоваться регулярным выражением \ > — признаком конца слова:
$ grep '48\>' data.f
48 Dec ЗВС1997 LPSX 68.00 LVX2A 138
8.1.8. Игнорирование регистра символов
По умолчанию команда grep чувствительна к изменению регистра символов. Чтобы провести поиск без учета регистра, воспользуйтесь опцией -i. В файле data.f обозначение месяца Sept встречается как в верхнем, так и в нижнем регистре. Поэтому для отбора строк обоих видов следует применить такую команду:
$ grep -i "sept" data.f
483 Sept 5AP1996 USP 65.00 LVX2C 189
216 sept 3ZL1998 USP 86.00 KVM9E 234
8.2. Команда grep и регулярные выражения
С помощью регулярных выражений можно задавать более сложные критерии фильтрации информации. При работе с регулярными выражениями следует заключать шаблон поиска в одинарные кавычки. Это позволит защитить все встречающиеся в нем специальные символы от интерпретатора shell, который в противном случае может "перехватывать" их у команды grep.
8.2.1. Выбор символов из списка
В предыдущей главе мы уже отмечали, что с помощью оператора [ 3 можно задать диапазон или список символов, включаемых в шаблон поиска. Предположим, требуется извлечь из файла data.f строка заказов, сделанных в городах, код которых равен 483 или 484. Поставленную задачу решает следующая команда:
$ grep '48[34]' data.f
493 Sept 5AP1996 USP 65.00 LVX2C 189
484 nov 7PL1996 CAD 49.00 PLV2C 234
483 may 5PA1998 asp 37.00 KVM9D 644
8.2.2. Инверсия шаблона с помощью метасимвола ""