При установленной переменной FIELDWIDTHS awk будет игнорировать переменную FS и находить поля данных в соответствии со сведениями об их ширине, заданными в FIELDWIDTHS.
Предположим, имеется файл testfile, содержащий такие данные:
1235.9652147.91
927-8.365217.27
36257.8157492.5
Известно, что внутренняя организация этих данных соответствует шаблону 3-5-2-5, то есть, первое поле имеет ширину 3 символа, второе — 5, и так далее. Вот скрипт, который позволит разобрать такие записи:
$ awk 'BEGIN{FIELDWIDTHS="3 5 2 5"}{print $1,$2,$3,$4}' testfile
Посмотрим на то, что выведет скрипт. Данные разобраны с учётом значения переменной FIELDWIDTHS, в результате числа и другие символы в строках разбиты в соответствии с заданной шириной полей.
Переменные RS и ORS задают порядок обработки записей. По умолчанию RS и ORS установлены на символ перевода строки. Это означает, что awk воспринимает каждую новую строку текста как новую запись и выводит каждую запись с новой строки.
Иногда случается так, что поля в потоке данных распределены по нескольким строкам. Например, пусть имеется такой файл с именем addresses:
Person Name
123 High Street
(222) 466-1234
Another person
487 High Street
(523) 643-8754
Если попытаться прочесть эти данные при условии, что FS и RS установлены в значения по умолчанию, awk сочтёт каждую новую строку отдельной записью и выделит поля, опираясь на пробелы. Это не то, что нам в данном случае нужно.
Для того, чтобы решить эту проблему, в FS надо записать символ перевода строки. Это укажет awk на то, что каждая строка в потоке данных является отдельным полем.
Кроме того, в данном примере понадобится записать в переменную RS пустую строку. Обратите внимание на то, что в файле блоки данных о разных людях разделены пустой строкой. В результате awk будет считать пустые строки разделителями записей. Вот как всё это сделать:
$ awk 'BEGIN{FS="\n"; RS=""} {print $1,$3}' addresses
Как видите, awk, благодаря таким настройкам переменных, воспринимает строки из файла как поля, а разделителями записей становятся пустые строки.
Помимо встроенных переменных, о которых мы уже говорили, существуют и другие, которые предоставляют сведения о данных и об окружении, в котором работает awk:
ARGC — количество аргументов командной строки.
ARGV — массив с аргументами командной строки.
ARGIND — индекс текущего обрабатываемого файла в массиве ARGV.
ENVIRON — ассоциативный массив с переменными окружения и их значениями.
ERRNO — код системной ошибки, которая может возникнуть при чтении или закрытии входных файлов.
FILENAME — имя входного файла с данными.
FNR — номер текущей записи в файле данных.
IGNORECASE — если эта переменная установлена в ненулевое значение, при обработке игнорируется регистр символов.
NF — общее число полей данных в текущей записи.
NR — общее число обработанных записей.
Переменные ARGC и ARGV позволяют работать с аргументами командной строки. При этом скрипт, переданный awk, не попадает в массив аргументов ARGV. Напишем такой скрипт:
$ awk 'BEGIN{print ARGC,ARGV[1]}' myfile
После его запуска можно узнать, что общее число аргументов командной строки — 2, а под индексом 1 в массиве ARGV записано имя обрабатываемого файла. В элементе массива с индексом 0 в данном случае будет «awk».
Переменная ENVIRON представляет собой ассоциативный массив с переменными среды. Опробуем её:
$ awk '
BEGIN{
print ENVIRON["HOME"]
print ENVIRON["PATH"]
}'
Переменные среды можно использовать и без обращения к ENVIRON. Сделать это, например, можно так:
$ echo | awk -v home=$HOME '{print "My home is " home}'
Переменная NF позволяет обращаться к последнему полю данных в записи, не зная его точной позиции:
$ awk 'BEGIN{FS=":"; OFS=":"} {print $1,$NF}' /etc/passwd
Эта переменная содержит числовой индекс последнего поля данных в записи. Обратиться к данному полю можно, поместив перед NF знак $.
Переменные FNR и NR, хотя и могут показаться похожими, на самом деле различаются. Так, переменная FNR хранит число записей, обработанных в текущем файле. Переменная NR хранит общее число обработанных записей. Рассмотрим пару примеров, передав awk один и тот же файл дважды:
$ awk 'BEGIN{FS=","}{print $1,"FNR="FNR}' myfile myfile
Передача одного и того же файла дважды равносильна передаче двух разных файлов. Обратите внимание на то, что FNR сбрасывается в начале обработки каждого файла.
Взглянем теперь на то, как ведёт себя в подобной ситуации переменная NR:
$ awk '
BEGIN {FS=","}