Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Операционная система UNIX.doc
Скачиваний:
94
Добавлен:
01.05.2014
Размер:
1.67 Mб
Скачать

10.21.2. Разделители ввода

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

поле 1 поле 2

поле 1

поле 1

Если в качестве разделителя полей используется символ табуляции, то лидирующие пробелы не отбрасываются.

Разделитель поля может быть установлен при помощи регулярного выражения при присваивоении значения встроенной переменной FS.

Например:

BEGIN { FS = ",[\t] * | ([\t]+" }

переделывает разделитель поля каждой строки в запятую и следующий за ней символ новой строки или табуляции, и каждую строку с символами пустой строки или табуляции без запятой. FS может быть установлен в командной строке с аргументом -F:

Пример.

awk -F ' (, [\t]*) | ([\t]+)' '...'

а выполняет те же действия, что и в предыдущем примере.

Регулярные выражения используются как разделители поля для поиска самых длинных строк (как в sub()), но не нулевых строк.

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

Соседние файлы в предмете Операционные системы