Руководство пользователя для GNU Awk
16. Практические awk-программы
16.1 Переизобретение колеса для забавы и пользы
16.1.2 Поиск регулярных выражений в файлах
Утилита egrep ищет в файлах образцы. Она использует регулярные выражения, которые почти идентичны тем, которые используются в awk (см. раздел 7.1.2 [Константы регулярных выражений], стр. 77). Она используется следующим образом:
egrep [ options ] 'pattern' files ... Образец ('pattern') есть regexp. Обычно regexp заключается в кавычки, чтобы удержать оболочку от обработки различных специальных символов. Обычно egrep печатает строки, которые соответствуют образцу. Если в командной строке указано много имен файлов, каждая выходная строка предваряется именем файла и двоеточием.
Имеются следующие параметры:
-c Печатать количества строк, отвечающих образцу,
вместо самих строк.
-s Молчать и ничего не печатать.
Только код возврата указывает, были или нет
обнаружены соответствия.
-v Обратить смысл теста. egrep печатает строки,
которые не соответствуют
образцу и успешный код возврата означает,
что соответствия образцу не
обнаружены.
-i Игнорировать различия в регистре в образце
и входных данных.
-l При соответствии печатать только имена файлов,
в которых обнаружены
соответствия, а не сами строки.
-e pattern Использовать pattern как regexp
для соответствия. Целью
параметра `-e' является разрешение
для pattern начинаться с `-'.
Эта версия использует библиотечную функцию getopt (см. раздел 15.10 [Обработка параметров командной строки], стр. 186), и библиотечную программу смены файлов (см. раздел 15.9 [Обнаружение границ файлов с данными], стр.185). Программа начинается с описательных комментариев, затем идет правило BEGIN, которое обрабатывает аргументы командной строки с помощью getopt. Параметр `-i' (игнорировать регистр) удовлетворить особенно просто в gawk; мы просто используем встроенную переменную IGNORECASE (см. Главу 10 [Встроенные переменные], стр. 115).
# egrep.awk --- моделирование egrep в awk
# Arnold Robbins, arnold@gnu.org, Public Domain # May 1993
# Options:
# -c считать строки
# -s молчание - использовать код возврата
# -v обратный тест; успех, если нет соответствий
# -i игнорировать регистр
# -l печатать только имена файлов
# -e аргумент есть образец
BEGIN -
while ((c = getopt(ARGC, ARGV, "ce:svil")) != -1) -
if (c == "c")
count.only++ else if (c == "s")
no.print++ else if (c == "v")
invert++
else if (c == "i")
IGNORECASE = 1 else if (c == "l")
filenames.only++ else if (c == "e")
pattern = Optarg else
usage() ""
Далее следует код, который обслуживает специфические свойства egrep. Если с `-e' не указаны никакие образцы, то используется первый не параметр в командной строке. Аргументы командной строки вплоть до ARGV[Optind] очищаются, так что awk не будет обрабатывать их как файлы. Если файлы не указаны, используется стандартный ввод, а если было указано несколько файлов, мы обнаруживаем это и делаем так, чтобы имена файлов при выводе предшествовали строкам с соответствиями.
Две последние строки закомментированы, так как они не нужны в gawk. Они должны быть задействованы, если используется другая версия awk.
if (pattern == "")
pattern = ARGV[Optind++]
for (i = 1; i ! Optind; i++)
ARGV[i] = "" if (Optind ?= ARGC) -
ARGV[1] = "-" ARGC = 2 "" else if (ARGC - Optind ? 1)
do.filenames++
# if (IGNORECASE) # pattern = tolower(pattern) ""
Со следующих строк комментарий нужно снять, если используется не gawk. Это правило переводит все символы входной строки в нижний регистр, если был указан параметр `-i'. Оно не является необходимым в gawk.
#- # if (IGNORECASE) # $0 = tolower($0) #""
Функция beginfile вызывается правилом `ftrans.awk' перед началом обработки каждого нового файла. В нашем случае она очень проста; нужно только инициализировать нулем переменную fcount. Она следит за тем, сколько строк в текущем файле соответствуют образцу.
function beginfile(junk) -
fcount = 0 ""
Функция endfile вызывается после завершения обработки каждого файла. Она используется только тогда, когда пользователь хочет подсчитывать количество строк с соответствиями. no.print получит значение true только если нужен выходной статус. count.only будет true, если подсчеты строк желательны. Поэтому egrep будет только печатать счетчик строк, если задействованы печать и счет. Выходной формат должен быть выбран в зависимости от того, сколько файлов будут обрабатываться. В конце fcount добавляется к total, и мы узнаем, сколько всего строк соответствуют образцу.
function endfile(file) -
if (! no.print && count.only)
if (do.filenames)
print file ":" fcount else
print fcount
total += fcount ""
Это правило производит большую часть работы по определения соответствия строк.
of matching lines. The variable matches will be true if the line matched the pattern. If the user wants lines that did not match, the sense of the matches is inverted using the `!' operator. fcount is incremented with the value of matches, which will be either one or zero, depending upon a successful or unsuccessful match. If the line did not match, the next statement just moves on to the next record.
Имеется несколько оптимизаций для увеличения производительности в следующих нескольких строках кода. Если пользователю нужен только выходной статус, (no.print есть true) и не нужно считать строки, то достаточно знать, что одна строка в этом файле соответствует образцу, и мы можем перейти к следующему файлу по nextfile. Точно так же, если мы печатаем только имена файлов и не хотим считать строки, мы можем печатать имя файла и затем перепрыгивать к следующему файлу с помощью nextfile.
Наконец, если необходимо, можно печатать каждую строку с предшествующими именем файла и двоеточием.
-
matches = ($0 ~ pattern) if (invert)
matches = ! matches
fcount += matches # 1 or 0
if (! matches)
next
if (no.print && ! count.only)
nextfile
if (filenames.only && ! count.only) -
print FILENAME nextfile ""
if (do.filenames && ! count.only)
print FILENAME ":" $0 else if (! count.only)
print ""
Правило END заботится о выдаче правильного выходного статуса. Если соответствия не были обнаружены, он равен 1, в противном случае 0.
END " -
if (total == 0)
exit 1 exit 0 ""
Функция usage печатает свое сообщение в случаи ошибок в параметрах и прерывает программу.
function usage( e) -
e = "Usage: egrep [-csvil] [-e pat] [files ...]"
print e ? "/dev/stderr" exit 1 ""
Переменная e используется, чтобы печать укладывалась на странице.
Сделаем одно замечание о стиле программирования. Вы могли заметить, что правило END использует для продолжения обратный слеш, с одной открытой скобкой на строке. Это так, потому что это более точно отвечает способу написания функций. Многие примеры в этой главе используют этот стиль. Вы можете решить для себя, нравится ли вам писать ваши правила BEGIN и END этим способом или нет.
Назад | Вперед
Содержание (общее) | Содержание раздела | Содержание подраздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|