руководство пользователя для gnu awk
10. встроенные переменныеэффективное awk-программирование
большинство awk-переменных доступны вам для использования в нужных вам целях; они изменяются только вашей программой и никогда не влияют ни на что кроме условий, проверяемых вашей программой. но несколько переменных в awk имеют специальное назначение. некоторые из них awk автоматически проверяет, так что они позволяют вам сообщать интерпретатору определенную информацию. другие awk автоматически устанавливает, так что они несут информацию от awk к вашей программе. в этой главе описаны все встроенные переменные gawk. большинство из них описываются также в главах, касающихся их областей активности. 10.1 встроенные переменные, которые управляют действиями awkприведем алфавитный список переменных, которые вы можете изменять для контроля за некоторыми действиями awk. переменные, специфичные для gawk, помечены звездочками `*'. convfmtэта цепочка управляет превращениями чисел в цепочки (см. раздел 7.4 [конверсии цепочек и чисел], стр. 81). она работает в качестве первого аргумента функции sprintf (см. раздел 12.3 [встроенные функции для манипуляций с цепочками], стр. 137). ее значение по умолчанию есть "%.6g". convfmt была введена в стандарте posix. fieldwidths *это разделенный пробелами список столбцов, который сообщает gawk, как расщеплять ввод с фиксированными границами для колонок. это экспериментальная возможность. присваивание в fieldwidths отменяет использование fs для разделения полей. см. раздел 5.6 [чтение данных фиксированной ширины], стр. 49, содержащий детали. если gawk работает в режиме совместимости (см. раздел 14.1 [параметры командной строки], стр.161), то fieldwidths не оказывает специального влияния и операции по выделению полей производятся только на основе значения fs. fsfs представляет входной разделитель полей (см. раздел 5.5 [указания того, как разделяются поля], стр. 44). ее значение есть одно-символьная цепочка или много символьное регулярное выражение, которое соответствует разделителям между полями в входной записи. если значение есть пустая строка (""), то каждый символ в записи рассматривается как отдельное поле. значение ее по умолчанию есть " ", цепочка из одного пробела. как специальное исключение, это значение подразумевает, что всякая последовательность пробелов, символов табуляции и/или newlines есть отдельный разделитель. оно также побуждает игнорировать пробелы, знаки табуляции и newlines в начале и конце записи. значение fs можно устанавливать из командной строки с помощью параметра `-f': awk -f, 'program' input-filesесли gawk использует fieldwidths для разделения полей, то присваивание значения переменной fs заставит gawk возвратиться к нормальному, на основе fs, разделению полей. простой путь для этого просто написать `fs = fs', возможно, с пояснительным комментарием. ignorecase *если значение ignorecase не ноль и не пусто, то все сравнения цепочек и определения соответствий регулярным выражениям будут независимы от регистра. так, в соответствие regexp по `~' и `!~', функция gensub, gsub, index, match, split и sub, в окончаниях записей по rs и разделению полей по fs --- всюду будет игнорироваться регистр во всех операциях. значение ignorecase не влияет на индексацию в массивах. см. раздел 4.5 [чувствительность к регистру в соответствиях], стр. 33. если gawk работает в режиме совместимости, (см. раздел 14.1 [параметры командной строки], стр.161), то ignorecase не имеет специального значения и цепочки и операции с regexp чувствительны к регистру. ofmtэта цепочка управляет превращениями чисел в цепочки (см. раздел 7.4 [конверсии цепочек и чисел], стр. 81) при печати по оператору print. фактически она работает как первый аргумент функции sprintf (см. раздел 12.3 [встроенные функции для манипуляций с цепочками], стр. 137). ее значение по умолчанию есть "%.6g". ранние версии awk также использовали ofmt для спецификации формата при превращении чисел в цепочки в общих выражениях; теперь это делается согласно переменной convfmt. ofsэто выходной разделитель полей (см. раздел 6.3 [выходные разделители], стр. 63). он разделяет поля на выходе в операторе печати. по умолчанию имеет значение " ", цепочка из одного пробела. ors это выходной разделитель записей. он выдается в конце результата оператора печати. по умолчанию его значение есть "\n". (см. раздел 6.3 [выходной разделитель, стр. 63.) rsэто входной разделитель записей в awk. по умолчанию его значение есть цепочка из одного символа newline. это означает, что входная строка состоит из одной строки текста. это может быть и пустая цепочка, и в этом случае записи разделены полосой строк из пробелов или regexp, в котором записи разделяются соответствиями этому regexp во входном тексте. (см. раздел 5.1 [как ввод делится на записи], стр. 37.) subsepsubsep есть разделитель индексов. по умолчанию он равен "\034" и используется для разделения индексов в элементах многомерного массива. так, выражение foo["a", "b"] фактически есть foo["a\034b"] (см. раздел 11.9 [многомерные массивы], стр. 130). 10.2 встроенные переменные, которые передают информациюприведем алфавитный список переменных, которые awk устанавливает автоматически в определенных случаях для передачи информации вашей программе. переменные, специфичные для awk, отмечены звездочкой, `*'. argc argvаргументы командной строки, доступные awk-программам, хранятся в массиве с именем argv. argc есть число присутствующих аргументов командной строки. см. раздел 14.2 [другие аргументы командной строки], стр. 165. в отличие от большинства массивов awk, argv индексируется от 0 до argc \gamma 1. например: $ awk 'begin { > for (i = 0; i ! argc; i++) > print argv[i] > }' inventory-shipped bbs-list -| awk -| inventory-shipped -| bbs-list в этом примере argv[0] содержит "awk", argv[1] содержит "inventory-shipped", а argv[2] содержит "bbs-list". значение argc есть три, на один больше чем индекс последнего элемента в argv, поскольку элементы нумеруются с нуля. имена argc и argv, также как соглашение об индексации массива от 0 до argc \gamma 1, взяты из метода языка cи для доступа к элементам командной строки. см. раздел 10.3 [использование argc и argv], стр. 120, для сведений о том, как awk использует эти переменные. argind *индекс в argv текущего обрабатываемого файла. каждый раз, когда gawk открывает новый файл с данными для обработки, он устанавливает argind на индекс имени этого файла в argv. когда gawk обрабатывает входные файлы, выражение `filename == argv[argind]' всегда имеет значение true. эта переменная полезна при обработке файлов; она дает возможность узнать, как далеко программа продвинулась в списке файлов с данными и различать последовательные появления того же имени файла в командной строке. поскольку вы можете изменять значение argind в вашей awk-программе, gawk будет автоматически устанавливать ее на новое значение, когда открывается следующий файл. эта переменная является расширением в gawk. в других реализациях awk или в gawk в режиме совместимости (см. раздел 14.1 [параметр командной строки], стр. 161), ее нет. environвспомогательный массив, который содержит данные об окружении. его индексы --- имена переменных окружения. значения есть значения некоторых переменных окружения. например, environ["home"] может быть `/home/arnold'. изменения в этом массиве не влияют на окружение, передаваемое каким-нибудь программам, которые awk может породить через перенаправление или системными средствами. (это может быть в будущих версиях gawk.) некоторые операционные системы могут не иметь переменных окружения. на таких системах массив environ пуст (кроме environ["awkpath"]). errno *если произойдет системный сбой или при перенаправлении для getline, во время чтения по getline, или во время операции close, то errno будет содержать цепочку с описанием ошибки. эта переменная представляет расширение gawk. в других реализациях awk и в gawk в режиме совместимости (см. раздел 14.1 [параметры командной строки], стр. 161) она отсутствует. filenameэто имя файла, который awk читает в настоящее время. если никакие файлы с данными не указаны в командной строке, awk читает из стандартного ввода и filename содержит "-". filename изменяется каждый раз, когда читается новый файл (см. главу 5 [чтение входных файлов], стр. 37). внутри правила begin значение filename есть "", поскольку в это время еще нет обрабатываемых входных файлов (d.c.). fnrfnr есть номер текущей записи в текущем файле. fnr увеличивается каждый раз, когда читается новая запись (см. раздел 5.8 [явный ввод по getline], стр. 53). она инициализируется нулем каждый раз, когда начинается новый входной файл. некоторые ранние реализации unix awk инициализировали filename значением "-", даже если имеются файлы с данными для обработки. такое поведение было неверным, и не надо на него полагаться в ваших программах. nfnf содержит количество полей в текущей входной записи. nf устанавливается каждый раз, когда читается новая запись, когда создается новое поле или когда меняется $0 (см. раздел 5.2 [исследование полей], стр. 40). nrэто количество входных записей, которые awk обработала с начала выполнения программы (см. раздел 5.1 [как ввод разделяется на записи], стр. 37). nr изменяется каждый раз, когда читается новая запись. rlengthrlength есть длина подцепочки, выделенной функцией соответствия (match function) (см. раздел 12.3 [встроенные функции для действий над цепочками], стр. 137). rlength устанавливается при вызове функции соответствия. ее значение есть длина выделенной цепочки или \gamma 1, если соответствия не обнаружено. rstartrstart есть начальный индекс в символах подцепочки, найденной функцией соответствия (см. раздел 12.3 [встроенные функции для операций над цепочками], стр. 137). rstart устанавливается при вызове функции соответствия. ее значение есть позиция цепочки, с которой начинается выделенная подцепочка, или 0, если соответствия нет. rt *rt устанавливается каждый раз, когда читается запись. она содержит входной текст, который определен в rs, разделитель записей. переменная есть расширение gawk. в других реализациях awk или в gawk в режиме совместимости (см. раздел 14.1 [параметры командной строки], стр. 161), она не действует. замечание о nr и fnr.awk просто увеличивает обе эти переменные каждый раз при чтении записи, вместо присваивания им абсолютного значения количества прочтенных записей. это значит, что ваша программа может изменять эти переменные, и их новые значения будут увеличиваться при чтении дальнейших записей (d.c.). например: $ echo '1 > 2 > 3 > 4' | awk 'nr == 2 { nr = 17 } > { print nr }' -| 1 -| 17 -| 18 -| 19 до того, как fnr была добавлена к языку awk (см. раздел 17.1 [главные изменения между v7 и svr3.1], стр. 253), многие awk-програмы использовали это свойство для определения количества записей в файле, устанавливая nr на 0 при изменении filename. 10.3 использование argc и argvв разделе 10.2 [встроенные переменные, которые передают информацию], стр. 117, мы видели эту программу, описывающую информацию, содержащуюся в argc и argv: $ awk 'begin { > for (i = 0; i < argc; i++) > print argv[i] > }' inventory-shipped bbs-list -| awk -| inventory-shipped -| bbs-list в этом примере argv[0] содержит "awk", argv[1] содержит "inventoryshipped", и argv[2] содержит "bbs-list". заметим, что awk-программа не входит в argv. другие специальные опции командной строки, вместе с их аргументами, также не входят. это включает присваивания переменным, сделанным с параметром `-v' (см. раздел 14.1 [параметры командной строки], стр. 161). нормально присваивания переменным из командной строки рассматриваются как аргументы и показываются в массиве argv. $ cat showargs.awk -| begin { -| printf "a=%d, b=%d\n", a, b -| for (i = 0; i < argc; i++) -| printf "\targv[%d] = %s\n", i, argv[i] -| } -| end { printf "a=%d, b=%d\n", a, b } $ awk -v a=1 -f showargs.awk b=2 /dev/null -| a=1, b=0 -| argv[0] = awk -| argv[1] = b=2 -| argv[2] = /dev/null -| a=1, b=2 ваша программа может изменить argc и элементы argv. каждый раз, когда awk достигает конец входного файла, она использует следующий элемент argv как имя следующего входного файла. помещая туда разные цепочки, ваша программа может вмешаться в чтение файлов. вы можете использовать "-" для представления стандартного ввода. запоминая дополнительные элементы и продвигая argc, можно заставить ее читать дополнительные файлы. если уменьшать значение argc, то будут исключены входные файлы из конца списка. запоминая где-нибудь старые значения argc, ваша программа может трактовать исключенные аргументы как нечто иное, чем имена файлов. чтобы исключить файл из середины списка, запишите пустую цепочку ("") в argv на место имени файла. игнорировать имена файлов, замененных пустой цепочкой, есть специальная особенность awk. можно также использовать оператор delete для удаления элементов из argv (см. раздел 11.6 [оператор delete], стр. 128). все эти действия обычно производятся из правила begin, до фактического начала обработки ввода. см. раздел 16.1.4 [разделение большого файла на части], стр. 217, и раздел 16.1.5 [дуплицирование результата в нескольких файлах], стр. 219, как пример разных путей удаления элементов из argv. следующий фрагмент обрабатывает argv, чтобы исследовать, а затем удалить параметры командной строки. begin { for (i = 1; i < argc; i++) { if (argv[i] == "-v") verbose = 1 else if (argv[i] == "-d") debug = 1 else if (argv[i] ~ /^-?/) { e = sprintf("%s: unrecognized option -- %c", argv[0], substr(argv[i], 1, ,1)) print e > "/dev/stderr" } else break delete argv[i] } } чтобы фактически перенести параметры в awk-программу, нужно закончить awk-параметры символами `--' и затем ввести ваши параметры, подобно следующему: awk -f myprog -- -v -d file1 file2 ...это не необходимо : пока не указано `--posix', gawk по умолчанию кладет всякий неопознанный параметр в argv для использования awk-программой. как только он увидит незнакомый параметр, gawk перестает искать другие параметры, которые он иначе мог бы распознать. предыдущий пример с gawk был бы таким: gawk -f myprog -d -v file1 file2 ...поскольку `-d' не есть правильный параметр gawk, последующее `-v' передается awk-программе. |
<<< | оглавление | >>> |