Руководство пользователя для GNU Awk
15. Библиотека функций awk
15.9 Отметка границ файлов с данными
Правила из BEGIN и END каждое вычисляются только один раз, в начале и в конце awk-программ (см. раздел 8.1.5 [Специальные образцы BEGIN и END], стр. 100). Мы (авторы gawks) однажды встретили пользователя, который ошибочно полагал, что правило BEGIN должно выполняться при начале каждого файла с данными, а END --- в конце каждого файла. Когда ему объяснили, что дело обстоит не так, оп попросил, чтобы в gawk добавили новые специальные образцы, называемые BEGIN.FILE END.FILE с желаемым им поведением. Он даже снабдил нас кодом, реализующим эти действия.
После некоторых раздумий, я вышел с следующей библиотечной программой. Она организует вызов написанных пользователем функций, beginfile и endfile, в начале и конце каждого файла с данными. Кроме решения проблемы посредством только девяти(!) строк кода, она переносима: работает с любой реализацией awk.
# transfile.awk # # Дает пользователю возможность переноса имени файла #
# Пользователь должен определить функции beginfile() и endfile()
#каждая берет имя файла соответственно при старте или окончании
# # Arnold Robbins, arnold@gnu.org, January 1992 # Public Domain
FILENAME != .oldfilename " -
if (.oldfilename != "")
endfile(.oldfilename) .oldfilename = FILENAME beginfile(FILENAME) ""
END - endfile(FILENAME) ""
Этот файл должен быть загружен перед "главной" программой пользователя, так чтобы правило, которое он содержит, вычислялось первым. Это правило полагается на awk-переменную FILENAME, которая автоматически меняется для каждого нового файла с данными. Текущее имя файла сохраняется в частной переменной .oldfilename. Если FILENAME не равно .oldfilename, то обрабатывается новый файл с данными и необходимо вызывать endfile для старого файла. Поскольку endfile должен вызываться только когда обработка файла закончена, программа сначала проверяет, что .oldfilename не пуста.
Затем программа присваивает имя текущего файла переменной .oldfilename и вызывает beginfile для нового файла. Поскольку, подобно всем awk-переменным, .oldfilename инициализируется пустой строкой, это правило правильно выполняется и для первого файла с данными. Программа также имеет правило END для завершающей обработки последнего файла. Поскольку это правило END приходит перед всеми правилами END в "главной" программе, сначала будет вызвана endfile. И опять значение кратных правил BEGIN END должно быть ясно.
Эта версия сталкивается с теми же трудностями, что и первая версия nextfile (см. раздел 15.2 [Реализация nextfile в виде функции], стр. 170). Если один и тот же файл с данными встретится два раза подряд в командной строке, то endfile и beginfile не будут выполняться в конце первого прохода и в начале второго. Проблему решает следующая версия.
# ftrans.awk --- обрабатывает переходы файлов с данными
# # пользователь определяет функции beginfile() и endfile()
# # Arnold Robbins, arnold@gnu.org, November 1992 # Public Domain
FNR == 1 -
if (.filename. != "")endfile(.filename.)
.filename. = FILENAME beginfile(FILENAME) ""
END - endfile(.filename.) ""
В разделах 16.1.7 [Подсчеты], стр. 225, вы увидите, как эти библиотечные функции могут использоваться и как это упрощает написание главной программы.
Назад | Вперед
Содержание (общее) | Содержание раздела
Если Вы не нашли что искали, то рекомендую воспользоваться поиском по сайту:
|