Библиотека сайта rus-linux.net
Руководство по 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 |