10.22. Многострочные записи

Обычно записи разделяются символами новой строки, так что каждая строка яавяется записью. Такой порядок можно изменить. Если пременная RS - разделитель встроенных записей - установлен в значение "пустая строка", как в:

	BEGIN { RS = "" }
то записи вводного файла могут занимать несколько строк. Последовательность пустых строк разделяет записи. Для обработки многострочных записей в общем случае может использоваться:
	BEGIN { RS = ""; FS = "\n" }
установка в качестве разделителя записи символ пустой строки и разделителя поля - символ новой строки. Таким образом, каждая строка является одним полем. Однако длина записи ограничена (обычно 2500 символов).

10.23. Функция getline

Способность awk автоматически разбивать вводной файл на записи длиной более чем одна строка, не отвечает требованиям некоторых задач. Например, если записи разделены не пустыми строками, а чем-нибудь другим, то установка RS в ноль не работает. В таком случае программа должна управлять разбиением каждой записи на поля. Здесь дано несколько советов.

Функция getline может быть использована для чтения ввода либо из текущего вводного файла, либо из файла или канала, перенаправленного аналогично printf.

getline вызывает следующую вводную запись и выполняет над ней нормальную операцию по разбиению на поля. Он устанавливает NF, NR, FNR. getline возвращает 1, если запись существует, 0 - если найден конец файла и -1, если появляется ошибка. (Например, невозможно открыть файл).

Проиллюстрируем выше изложенное. Предположим, вы имеете вводные данные, состоящие из многострочных записей. Каждая запись начинается строкой, в начале которой стоит STOP. Следующая программа awk обрабатывает эти многострочные записи, помещая строки записи в последовательные входы массива:

	f[1] f[2] ... f[nf]
Как только встретится строка, содержащая STOP, то запись может быть обработана в виде данных массива f:
        /^START/  {
                   f[nf-1] = $0
                   while (getline && $0 !~ /~STOP/ }
                          f[++nf] = $0
                    # now process the data in f[1] ... f[nf]
                    ...
        }

Обратите внимание на тот факт, что && вычисляет операнды слева направо и останавливает вычисление как только один из них будет истинным.

То же самое задание может быть выполнено с помощью следующей программы:

        /^START/ && nf == 0   { f[nf-1] = $0 }
        nf > 1                { f[++nf] = $0 }
        /^STOP/    # now process the data in f[1] ... f[nf]
                               ...
                               nf = 0
        }
Оператор:
	getline x 
читает из файла вместо текущего ввода. Значение NR и FNR не устанавливается, но разбиение полей выполняется и устанавливается значение NF.

Оператор:

	getline x < "file"
получает следующую запись из файла и направляет в x; разбиение не производится и значение NF, NR и FNR не устанавливается.

Если имя файла является выражением, то оно должно быть заключено в круглые скобки для вычисления:

	while ( getline x < (ARGV[1] ARGV[2]) ) { ... }
т. к. операция "<" имеет больший приоритет, чем конкатенация. Без круглых скобок оператор подобный:
	getline x < "tmp" FILENAME 
указывает , что нужно читать в файл "x" из файла "tmp", а не в "tmp" <значение FILENAME>.

Если вы используете оператор, подобный:

	while ( getline x < file) { ... }
то цикл будет бесконечным, если файл не может быть считан, т.к. getline возвращает -1 в этом случае. Лучше такой тест сделать с помощью следующего оператора:
	while ( getline x < file > 0) { ... }
Вы также можете направить вывод другой команды прямо getline. Например, оператор:
	while ( "who" | getline )
                n++
выполняет who и направляет свой вывод в getline. Каждая итерация цикла while читает более одной записи и увеличивает переменную n. После завершения цикла while, n содержит количество пользователей.

Оператор:

	"date" | getline d 
направляет вывод из date в переменную d, таким образом устанавливается в d текущая дата.

В табл. 27 суммируется рассказанное в этом пункте.

Таблица 27
Функция getline

Форма Устанавливаемое значение
getline $0, NF, NR, FNR
getline var var, NR, FNR
getline < file $0, NF
getline var < file var
cmd | getline $0, NF
cmd | getline var

10.24. Аргументы командной строки

В программе awk могут использоваться аргументы командной строки: массив ARGV содержит элементы ARGV[0], ... ARGV[ARGC-1], где ARGC - счетчик, ARGV[0] - имя программы (в общем случае - awk), остальное - любые поддерживаемые аргументы, исключая программы и необязательные аргументы).

Следующая командная строка содержит программу awk, отражающую аргументы, которые появляются после имени программы:

        awk '
        BEGIN  {
                for ( i = 1; i < ARGC; i++ )
                     printf "%s ", ARGV[i]
                printf "\n"
        }' $*

Аргументы могут быть модифицированы или добавлены. ARGC может изменяться. После окончания вводного файла awk обращается к следующему ненулевому элементу ARGV (увеличив текущее значение ARGC-1) как к имени следующего вводного файла.

Исключением из правила является то, что аргумент считается именем файла, если он имеет форму:

	var-value 

Переменная var принимает значение value, как при операции присвоения. Если value является строкой, то кавычки не нужны.

Назад | Содержание | Вперед

Copyright © CIT