Функции этого раздела просматривают или изменяют текст одной или более цепочек. Необязательные параметры заключены в квадратные скобки.
index(in, find)
Ищет в цепочке in первое вхождение цепочки find и возвращает номер символа в цепочке in, с которого начинается это вхождение. Например:
$ awk 'BEGIN - print index("peanut", "an") ""'
a 3
ПРИМЕЧАНИЕ 1
Генерируемые компьютером случайные числа не являются вполне случайными. Они технически известны как "псевдослучайные." Это значит, что хотя числа в последовательности кажутся случайными, можно фактически генерировать ту же самую последовательность снова и снова. Если цепочка find не обнаружена, функция index выдает ноль. (Вспомним, что позиции в цепочке awk нумерует с единицы.)
length([string])
Выдает количество символов в цепочке string. Если string есть число, то выдается длина цифровой цепочки, представляющей это число. Например, length("abcde") есть пять. В отличие от этого, length(15 * 35) вырабатывает три. Почему? Но 15 * 35 = 525, а 525 конвертируется в цепочку "525", которая содержит три символа! Если аргумент не указан, length выдает длину $0. В старых версиях можно было вызывать функцию length без всяких скобок. Это "резко осуждается" в стандарте POSIX. Что означает, что такая возможность будет удалена со временем из будущих версий стандарта. Поэтому, для максимальной переносимости ваших программ, нужно всегда употреблять скобки.
match(string, regexp)
Функция match ищет в цепочке string самую длинную, самую левую подцепочку, соответствующую регулярному выражению regexp. Она возвращает номер позиции начала найденной подцепочки (один, если она начинается в начале string). Если соответствия не найдено, возвращается ноль. Функция match устанавливает номер найденной позицию в встроенную переменную RSTART. Она также устанавливает в встроенную переменную RLENGTH длину упомянутой подцепочки. Если таковая не обнаружена, RSTART и RLENGTH получают значения ноль \Gamma 1.
Это программа разыскивает строки, которые соответствуют регулярному выражению, присвоенному переменной regex. Это регулярное выражение может меняться. Если первое слово в строке есть `FIND', regex заменяется вторым словом этой строки. Поэтому, если дано:
FIND ru+n
My program runs
but not very quickly
FIND Melvin JF+KM
This line is property of Reality Engineering Co.
Melvin was here.
awk напечатает:
Match of ru+n found at 12 in My program runs
Match of Melvin found at 1 in Melvin was here.
split(string, array [, fieldsep])
Эта функция разделяет string на куски, разделенные цепочками fieldsep, и записывает куски в массив array. Первый кусок запоминается в array[1], второй в array[2], и т.д. Строковое значение третьего аргумента fieldsep есть regexp, указывающее, где расщеплять строку (как FS может быть regexp для разделения входных записей). Если fieldsep опущено, используется значение FS. split возвращает количество созданных элементов.
Функция split расщепляет цепочки на куски подобно тому как входные строки расщепляются на поля. Например, split("cul-de-sac", a, "-") расщепляет цепочку `cul-de-sac' на три поля, используя `-' как сепаратор. Она устанавливает содержимое массива следующим образом: a[1] = "cul" a[2] = "de" a[3] = "sac" Этот вызов возвращает значение три. Как и в случае разделения входных полей, если значение fieldsep есть " ", начальные и конечные whitespace игнорируются и элементы разделяются группами whitespace. Также как с разделением входных полей, если fieldsep есть пустая цепочка, каждый отдельный символ цепочки поступает в отдельный элемент массива. (Это есть специальное расширение gawk.) Недавние реализации awk, включая gawk, допускают в качестве третьего аргумента как константу regexp (/abc/), так и цепочку (d.c.). Стандарт POSIX также допускает это. До расщепления цепочки split вычеркивает все ранее существующие элементы массива array (d.c.). Если цепочка не соответствует fieldsep совсем, array будет иметь один элемент. Его значением будет исходная цепочка.
sprintf(format, expression1,...)
Эта функция возвращает (без печати) ту цепочку, которую напечатала бы функция
printf c теми же аргументами (см. раздел 6.5 [Использование оператора
printf для декоративной печати], стр. 64). Например:
sprintf("pi = %.2f (approx.)", 22/7) возвращает цепочку
"pi = 3.14 (approx.)".
sub(regexp, replacement [, target])
Функция sub изменяет значение target. Она ищет в target, рассматриваемой как цепочка, самую левую самую длинную подцепочку, соответствующую регулярному выражению regexp, распространяя поиск как можно дальше. Затем в цепочке target найденный текст заменяется на replacement и модифицированная цепочка становится новым значением target.
Эта функция --- особенная, потому что target используется не только для вычисления значения и не должна быть выражением, а только переменной, полем или элементом массива, чтобы записать туда измененное значение. Если этот аргумент опущен, по умолчанию используется и изменяется $0. Например, str = "water, water, everywhere" sub(/at/, "ith", str) меняет значение str на "wither, water, everywhere", заменяя самое левое и самое длинное вхождение `at' на `ith'. Функция sub возвращает количество сделанных подстановок (один или ноль).
Если replacement содержит специальный символ `&', он представляет точную подцепочку, соответствующую regexp. (Если regexp может соответствовать более чем одной цепочке, то эта точная подцепочка может изменяться).
Например:
awk '- sub(/candidate/, "& and his wife"); print ""'
заменяет первое вхождение `candidate' на `candidate and his wife'
в каждой входной строке. А вот другой пример:
awk 'BEGIN -
str = "daabaaa" sub(/a*/, "c&c", str) print str ""'
a dcaacbaaa
Здесь показано, как `&' может представлять непостоянные цепочки, а также иллюстрируется правило "самая левая самая длинная" в соответствии regexp (см. раздел 4.6 [Как много текста соответствует?], стр.34). Эффект от этого специального символа (`&') может быть исключен помещением перед ним в цепочке обратного слеш. Как обычно, чтобы вставить один обратный слеш в цепочку, нужно написать два подряд. Поэтому пишите `""&' в строковой константе для включения литерала `&' в replacement. Например, покажем, как заменить первый `--' в каждой строке с `&':
awk '- sub(/"--/, """&"); print ""'
Заметьте: как говорилось выше, третий аргумент sub должен быть переменной, полем или ссылкой на массив. Некоторые версии awk допускают в качестве третьего аргумента выражение, которое не является lvalue. В таких случаях sub будет искать образец и возвращать ноль или один, но результат подстановки (если будет) отбрасывается. Такие версии awk принимают выражения вида, подобного следующему: sub(/USA/, "United States", "the USA and Canada") Для исторической совместимости gawk допускает подобные коды. Однако, использование всяких других неизменяемых объектов в качестве третьего параметра приводит к фатальной ошибке и программа не исполняется.
Наконец, если regexp не есть константа regexp, оно превращается в цепочку, которая используется как regexp для соответствия.
gsub(regexp, replacement [, target])
Действует подобно sub, но заменяет все длиннейшие левые не перекрывающиеся соответствующие подцепочки, которые может найти. `g' в gsub означает "global," т.е. заменять повсюду.
Например:
awk '- gsub(/Britain/, "United Kingdom"); print ""' заменяет все вхождения цепочки `Britain' на `United Kingdom' во всех входных записях. Функция gsub возвращает число сделанных подстановок. Если переменная для поиска и замены, target, опущена, то используется вся входная запись $0. Как и в sub, символы `&' and `"' имеют специальный смысл и третий аргумент должен быть lvalue.
gensub(regexp, replacement, how [, target])
gensub есть общая функция подстановки. Подобно sub и gsub, она ищет в цепочке target подцепочку, соответствующую регулярному выражению regexp. В отличие от sub и gsub, модифицированная цепочка возвращается как результат функции, а оригинальная цепочка target не меняется. Если how есть цепочка, начинающаяся с `g' или `G', то gensub замещает все соответствия regexp на replacement. В противном случае how есть число, указывающее, какое соответствие regexp заменить. Если target отсутствует, вместо нее используется $0.
gensub имеет дополнительное свойство, отсутствующее в sub и gsub: возможность указывать компоненты regexp в тексте для замещения. Это делается с помощью скобок в regexp для отметки компонент и затем указанием `"n' в замещающем тексте, где n есть цифра от 1 до 9.
Например:
$ gawk ' ? BEGIN - ? a = "abc def" ?
b = gensub(/(.+) (.+)/, """2 ""1", "g", a) ? print b ? ""'
a def abc
Как сказано выше для sub, вы должны написать два обратных слеша для того чтобы вставить один в цепочку. В замещающем тексте последовательность `"0' представляет целый соответствующий текст, как это делает символ `&'. Следующий пример показывает, как можно использовать третий аргумент для указания, какое соответствие regexp должно быть заменено:
$ echo a b c a b c -- ? gawk '- print gensub(/a/, "AA", 2) ""'
a a b c AA b c
В этом случае по умолчанию $0 используется в качестве цепочки target. gensub возвращает новую цепочку как свой результат, который передается непосредственно в print для печати.
Если аргумент how есть цепочка, которая не начинается с `g' или `G', или если это число меньшее нуля, то производится только одна подстановка. Если regexp не соответствует target, то gensub возвращает исходное, не измененное значение target.
gensub есть расширение gawk; она недоступна в режиме совместимости (см. раздел 14.1 [Параметры командной строки], стр. 161).
substr(string, start [, length])
Возвращает подцепочку длины length цепочки string, начинающуюся с символа с номером start. Первый символ string имеет номер один.
Например, substr("washington", 5, 3) возвращает "ing".
Если length отсутствует, эта функция возвращает хвост цепочки string, который начинается с символа номер start. Например, substr("washington", 5) возвращает "ington". Весь хвост возвращается также, если length больше длины хвоста.
ЗАМЕЧАНИЕ: цепочке, возвращаемой substr, нельзя ничего присваивать. Так, будет ошибкой пытаться изменить часть цепочки подобно следующему:
string = "abcdef"
# попытка получить "abCDEf" не сработает:
substr(string, 3, 3) = "CDE"
или использовать substr как третий аргумент в sub или gsub:
gsub(/xyz/, "pdq", substr($0, 5, 20)) # WRONG
tolower(string)
Возвращает копию цепочки, в которой буквы верхнего регистра заменены на соответствующие буквы нижнего. Небуквенные символы не меняются. Например, tolower("MiXeD cAsE 123") вернет "mixed case 123".
toupper(string)
Возвращает копию цепочки, в которой буквы нижнего регистра заменены на соответствующие буквы верхнего регистра. Остальные символы не меняются. Например, toupper("MiXeD cAsE 123") возвратит "MIXED CASE 123".
Дополнительные сведения о `"' и `&' в sub, gsub и gensub
При использовании sub, gsub или gensub, стараясь получить литералы обратных слешей и амперсантов в замещающем тексте, необходимо помнить, что имеется несколько уровней обработки управляющих последовательностей.
Первый есть лексический уровень, когда awk читает программу и строит ее внутреннюю копию, которая будет интерпретироваться.
Затем следует уровень исполнения, когда awk фактически просматривает заменяющую цепочку и определяет, что генерировать.
На обоих уровнях awk ищет определенное множество символов, которые могут идти за обратным слешем. На лексическом уровне он ищет управляющие последовательности, перечисленные в разделе 4.2 [Управляющие последовательности], стр. 24. Так, для каждого `"' который awk будет обрабатывать на уровне исполнения, вы печатаете два `"' для лексического уровня. Когда символ, который не может быть в управляющей последовательности, следует за `"', Unix awk и gawk оба просто удаляют начальный `"'и кладут следующий символ в цепочку. Так, например, "a"qb" трактуется как "aqb".
На уровне исполнения различные функции обрабатывают последовательности из `"' и `&' различным образом. Ситуация, к несчастью, довольно сложная. Исторически функции sub и gsub рассматривают двух символьные последовательности `"&' специально; эта последовательность была заменена в генерированном тексте одним `&'. Все другие `"' в пределах замещающей цепочки, которые не предшествовали символу `&', были переданы без изменения.
Проиллюстрируем это таблицей:
Вы печатаете sub видит sub генерирует
"& & the matched text
""& "& a literal `&'
"""& "& a literal `&'
""""& ""& a literal `"&'
"""""& ""& a literal `"&'
""""""& """& a literal `""&'
""q "q a literal `"q'
Эта таблица показывает оба уровня: лексический уровень обработки, где нечетное количество обратных слешей становится четным для уровня исполнения , и обработку на уровне исполнения, проделываемую функцией sub. (Для упрощения следующие таблицы показывают только случай четного количества `"', обрабатываемых на лексическом уровне.)
Проблема с историческим подходом состоит в том, что нет способа получить литерал `"', за которым следует соответствующий образцу текст. Стандарт POSIX 1992 пытался разрешить эту проблему. Стандарт говорит, что sub and gsub ищут либо `"' либо `&' после `"'. Если какой-нибудь из них следует за `"', то этот символ выдается буквально. Интерпретация `"' `&' тогда становится такой:
Вы печатаете sub видит sub генерирует
& & the matched text
""& "& literal `&'
""""& ""& literal `"', then the matched text
""""""& """& a literal `"&'
Кажется, что проблема решена. К несчастью, слова в стандарте неясны. Он говорит фактически, что `"' отключает специальный смысл всех следующих символов, но это только для отличных от `"' и `&'. Такой специальный смысл непонятен. Такое определение приводит к двум проблемам.
1. Обратные слеши должны теперь дублироваться в цепочке замещения, что разрушает исторические программы awk.
2. Чтобы быть уверенным в переносимости awk-программ, каждому символу в замещающей цепочке должен предшествовать обратный слеш.
2 Стандарт POSIX пересматривается.
3 В связи с упомянутыми выше проблемами предложенный текст для измененного стандарта возвращается к правилам, которые более тесно соответствуют существующей практике. Предложенные правила имеют специальные случаи, которые позволяют выдавать `"' перед соответствующим текстом.
Вы печатаете sub видит sub генерирует
""""""& """& a literal `"&'
""""& ""& literal `"', followed by the matched text
""& "& literal `&'
""q "q literal `"q'
Короче, на уровне выполнения теперь имеются три специальные последовательности символов, `"""&', `""&' и `"&', в то время как исторически была только одна. Однако, как и в историческом случае, любой `"' , который не есть часть одной из упомянутых трех последовательностей, не является специальным и появляется в выходе буквально.
gawk 3.0 следует этим предложенным правилам POSIX для sub и gsub. Будут ли эти предложенные правила введены в стандарт, в настоящее время не известно. Последующие выпуски gawk будут следовать стандарту и реализовать указания окончательной его версии; также будет изменена и соответствующая часть этой книги.
Правила для gensub значительно проще. На уровне исполнения, всякий раз когда gawk видит `"', если следующий символ есть цифра, то текст, который соответствует заключенному в скобки подвыражению, идет в генерируемый выход. В противном случае, независимо от следующего символа, этот символ идет в генерируемый текст, а `"' не идет.
Вы печатаете gensub видит gensub генерирует
& & the matched text
""& "& literal `&'
"""" "" literal `"'
""""& ""& literal `"', then the matched text
""""""& """& literal `"&'
""q "q literal `q'
Вследствие сложности обработки на лексическом и исполнительном уровнях и специальных случаев для sub и gsub, мы рекомендуем использовать gawk и gensub, когда нужно сделать подстановки.
2 Это следствие было определенно непреднамеренным.
3 Как в апреле 1999, с окончательным санкционированием и публикацией где-то в in 1997.