Оператор nextfile, описанный в разделе 9.8 [Оператор nextfile], стр. 112, есть специальное расширение gawk. Он недоступен в других реализациях awk. В настоящем разделе приведены две версии функции nextfile, которые можно использовать для моделирования соответствующего оператора gawk, если невозможно использовать gawk.
Вот первая попытка написать функцию nextfile.
# nextfile --- пропустить оставшиеся записи в текущем файле
# это должно быть прочитано до "главной" программы awk
function nextfile()
- .abandon. = FILENAME; next "" .abandon. == FILENAME - next ""
Этот файл должен быть вставлен перед главной программой, потому что он содержит правило, которое должно выполняться c самого начала. Это правило сравнивает имя текущего файла данных (которое всегда находится в переменной FILENAME) с индивидуальной переменной, названной .abandon.. Если имя файла соответствует, то действие правила выполняет оператор next, то есть перейти к следующей записи. (Употребление `.' в имени перемененной есть соглашение. Оно подробнее обсуждается в разделе 15.13 [Наименование глобальных переменных библиотечных функций], стр. 202). Использование оператора next фактически создает цикл, который читает все записи из текущего файла с данными. В итоге достигается конец файла и открывается новый файл с данными, изменяющий значение FILENAME. Когда это произойдет, сравнение .abandon. с FILENAME выдает false и выполнение продолжается с первого правила "реальной" программы.
Сама функция nextfile просто устанавливает значение .abandon. и затем выполняет оператор next для запуска цикла.1
Эта начальная версия имеет некоторую неточность. Что произойдет, если тот же самый файл с данными указан дважды в командной строке, два раза подряд, или даже с присваиванием значения переменной между двумя указаниями имени файла? В таком случае программа пропустит второй файл, даже если она должна остановиться, когда достигнет конец первого из указанных. Вот вторая версия nextfile, которая решает эту проблему.
1 Некоторые реализации awk не позволяют вам выполнять next внутри тела функции. Необходимы какие-то другие приемы, если вы используете такую версию.
# nextfile --- пропустить оставшиеся в текущем файле записи
# правильно обрабатывать последовательные появления того же файла
# Arnold Robbins, arnold@gnu.org, Public Domain
# May, 1993
# это должно быть прочтено до "главной" awk-программы
function nextfile()
- .abandon. = FILENAME; next "" .abandon. == FILENAME -
if (FNR == 1)
.abandon. = "" else
next ""
Действия nextfile не меняются. Она устанавливает .abandon. равным текущему имени файла и выполняет оператор next. Он читает следующую запись и увеличивает FNR, так что FNR получает по крайней мере значение два. Однако, если nextfile вызван для последней записи в файле, то awk закроет текущий файл с данными и перейдет к следующему. При этом FILENAME получит значение имени нового файла и FNR получит значение один. Если этот следующий файл есть тот же, что и предыдущий, .abandon. будет еще равно FILENAME. Однако, FNR будет равно единице, говоря нам, что мы имеем дело с новым файлом, не тем, который читали при выполнении функции nextfile. В этом случае .abandon. получает значение пустой цепочки, дальнейшего выполнения этого правила не происходит (пока nextfile не будет вызвана в следующий раз). Если же FNR имеет значением не единицу, то мы еще находимся в прежнем файле и программа выполняет оператор next для пропуска его конца.
Важным вопросом в этой точке будет такой: "если действия nextfile моделируются библиотечной функцией, зачем этот оператор встроен в gawk?" Это действительно важный вопрос. Дополнительные свойства при малой надобности приводят к более сложной и медленной программе, которую труднее поддерживать. Ответ состоит в том, что встраивание nextfile в gawk дает значительный выигрыш в эффективности. Если функция nextfile выполняется в начале большого файла, awk будет сканировать весь файл, расщепляя его на записи, чтобы пропустить его обработку. Встроенный оператор nextfile может просто закрыть немедленно файл и перейти к следующему, экономя много времени. Это особенно важно в awk, поскольку awk-программы обычно ориентированы на I/O (т.е. они большую часть времени тратят на ввод и вывод, а не на вычисления.