Наши партнеры








Книги по Linux (с отзывами читателей)

Библиотека сайта rus-linux.net

На главную -> MyLDP -> Электронные книги по ОС Linux
Руководство по Bash для начинающих
Назад Глава 6: Язык программирования GNU awk Вперед

Переменные Gawk

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

Разделитель входных полей

Разделитель полей, которым может быть либо один символ, либо регулярное выражение, управляет тем, как в awk происходит разбиение входной записи на поля. Входная запись проверяется на наличие последовательности символов, которые совпадают с определением разделителя; сами поля являются текстом, расположенным между совпавшими символами.

Разделитель полей представлен во встроенной переменной FS. Заметьте, эта переменная отличается от переменной IFS, используемой в POSIX-совместимых командных оболочках.

Значение переменной разделителя полей можно изменять в программе awk при помощи оператора присваивания =. Чтобы самая первая запись была прочитана с надлежащим разделителем, такое присваивание нужно это делать в начале выполнения скрипта еще до того, как будет обработана какая-нибудь входная строка. Для этого можно использовать специальный шаблон BEGIN.

В примере, приведенном ниже, мы создаем команду, которая отображает всех пользователей в вашей системе и выдает и их описание:

kelly is in ~> awk 'BEGIN { FS=":" } { print $1 "\t" $5 }' /etc/passwd
--output omitted--
kelly   Kelly Smith
franky  Franky B.
eddy    Eddy White
willy   William Black
cathy   Catherine the Great
sandy   Sandy Li Wong

kelly is in ~>

В скрипте awk это должно выглядеть следующим образом:

kelly is in ~> cat printnames.awk
BEGIN { FS=":" }
{ print $1 "\t" $5 }

kelly is in ~> awk -f printnames.awk /etc/passwd
--output omitted--

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

“Sandy L. Wong, 64 Zoo St., Antwerp, 2000X”

Вы пишете командную строку или скрипт, который выводит имя человека, указанного в этой записи:

awk 'BEGIN { FS="," } { print $1, $2, $3 }' inputfile 

Но человек может иметь ученую степень, и она может быть записана следующим образом:

Sandy L. Wong, PhD, 64 Zoo St., Antwerp, 2000X”

В случае этой строки ваш awk выдаст неправильный результат. Если необходимо, воспользуйтесь дополнительной командой awk или sed чтобы прийти к единому формату ввода данных.

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

Разделители выходного потока

Разделители полей выходного потока

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

kelly@octarine ~/test> cat test
record1         data1
record2         data2

kelly@octarine ~/test> awk '{ print $1 $2}' test
record1data1
record2data2

kelly@octarine ~/test> awk '{ print $1, $2}' test
record1 data1
record2 data2

kelly@octarine ~/test>

Когда запятые не используются, команда print при выводе трактует все элементы как один аргумент и разделитель выходного потока, заданный в переменной OFS по умолчанию, использоваться не будет.

Любая символьная строка, если ее присвоить этой встроенной переменной, может использоваться в выходном потоке в качестве разделителя полей.

Разделитель выходных записей

Выдача, делаемая всей инструкцией print, называется выходной записью. Каждая команда print выдает результат в одной выходной записи, а затем выдается строка, называемая разделителем выходных записей или ORS. Значением, используемым по умолчанию в этой переменной, является "\n", т. е. символ новой строки. Таким образом, каждая инструкция print создает отдельную строку.

Чтобы изменить способ разделения выходных полей и записей, назначьте переменным OFS и ORS новые значения:

kelly@octarine ~/test> awk 'BEGIN { OFS=";" ; ORS="\n-->\n" } \
{ print $1,$2}' test
record1;data1
-->
record2;data2
-->

kelly@octarine ~/test>

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

Количество записей

Во встроенной переменной NR хранится значение, указывающее число обработанных записей. Оно увеличивается на единицу после считывания новой строки. Вы можете использовать его в каждой выходной записи или в конце обработки, чтобы подсчитать общее количество записей:

kelly@octarine ~/test> cat processed.awk
BEGIN { OFS="-" ; ORS="\n--> done\n" }
{ print "Record number " NR ":\t" $1,$2 }
END { print "Number of records processed: " NR }

kelly@octarine ~/test> awk -f processed.awk test
Record number 1:        record1-data1
--> done
Record number 2:        record2-data2
--> done
Number of records processed: 2
--> done

kelly@octarine ~/test>

Переменные, определяемые пользователем

Помимо встроенных переменных, вы можете определять свои собственные переменные. Если в awk указывается переменная, которая еще не существовала (ранее не была определена), то это переменная создается и инициализируется пустой строкой. Во всех последующих обращениях к переменной ее значение будет таким, как оно было назначено последний раз. Переменные могут быть строками или числовыми значениями. Переменным можно также присваивать значения полей ввода.

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

kelly@octarine ~> cat revenues
20021009        20021013        consultancy     BigComp         2500
20021015        20021020        training        EduComp         2000
20021112        20021123        appdev          SmartComp       10000
20021204        20021215        training        EduComp         5000

kelly@octarine ~> cat total.awk
{ total=total + $5 }
{ print "Send bill for " $5 " dollar to " $4 }
END { print "---------------------------------\nTotal revenue: " total }

kelly@octarine ~> awk -f total.awk test
Send bill for 2500 dollar to BigComp
Send bill for 2000 dollar to EduComp
Send bill for 10000 dollar to SmartComp
Send bill for 5000 dollar to EduComp
---------------------------------
Total revenue: 19500

kelly@octarine ~>

Допускаются также сокращения в стиле C, такие как VAR+= value.

Дополнительные примеры

Пример из раздела "Запись выходных файлов" становится гораздо проще, если мы используем скрипт awk:

kelly@octarine ~/html> cat make-html-from-text.awk
BEGIN { print "<html>\n<head><title>Awk-generated HTML</title></head>\n<body bgcolor=\"#ffffff\">\n<pre>" }
{ print $0 }
END { print "</pre>\n</body>\n</html>" }

И команда, которая должна быть выполнена, также гораздо проще, когда вместо sed используется awk:

kelly@octarine ~/html> awk -f make-html-from-text.awk testfile > file.html
Примеры Awk в вашей системе

Мы вновь ссылаемся на директорий, в котором находятся скрипты init вашей системы. Введите, например, следующую команду, чтобы увидеть примеры практического более широкого использования команды awk:

grep awk /etc/init.d/* 

Программа printf

Для более точного управления выходным форматом, чем тот, что обычно обеспечивается командой print, используйте команду printf. В команде printf можно указывать ширину поля каждого элемента, а также указывать различные форматы чисел (например, будет ли указываться основание числа, выдаваться экспонента, следует ли выдавать знак числа, и сколько цифр будет выдаваться после десятичной точки). Это делается с помощью специальной строки, называемой строкой формата, в которой указывается, как и где выдавать другие аргументы.

Синтаксис такой же, как и для инструкции printf языка C; смотрите введение в C. Подробное пояснение имеется в документации по gawk.


Предыдущий раздел: Оглавление Следующий раздел:
Программа print   Подводим итоги главы 6