prevfile = FILENAME
}
NF > 0 {
if ($1 == lastword)
printf "double %s, file %s, line %d\n" ,$1, FILENAME, NR
for (i = 2; i <= NF; i++)
if ($i == $(i-1))
printf "double %s, file %s, line %d\n", $i, FILENAME, NR
if (NF > 0)
lastword = $NF
}' $*
*
$
Операция ++
означает автоувеличение операнда, а операция --
— его автоуменьшение.
Встроенная переменная FILENAME
хранит имя текущего входного файла. Поскольку в переменной NR
подсчитывается число строк с начала входного потока, мы изменяем ее значение всякий раз при изменении имени файла, чтобы точно указать строку с двойником.
Оператор if
— такой же, как в языке Си:
if (условие)
оператор1
else
оператор2
Если условие верно, то выполняется оператор1
; если оно ложно и если альтернативная часть присутствует, то выполняется оператор2
. Альтернативная часть не обязательна.
Цикл for
аналогичен таковому в языке Си, но отличается от цикла в языке shell
:
for (выражение1; условие; выражение2)
оператор
Цикл for
идентичен приведенному ниже оператору, который также допустим в программе awk
:
Выражение1 while (условие) {
оператор
выражение2
}
Например, конструкция
for (i=2; i <= NF; i++)
является циклом с i
, принимающим значения 2, 3 и т.д., включая число полей NF
.
Оператор break
вызывает немедленный выход из цикла while
или for
; оператор continue
инициирует переход к следующему шагу цикла (к условию в операторе while
или к выражению2
в операторе for
). Оператор next
вызывает чтение следующей входной строки и сопоставление ее с шаблонами с начала программы awk
, а оператор exit
— немедленный переход на действия, определенные в шаблоне END
.
Как и в большинстве языков программирования, в awk
есть массивы. В качестве простого примера приведем программу awk
, в которой каждая входная строка заносится в отдельный элемент массива, индексируемого номером строки, а затем они печатаются в обратном порядке:
$ cat backwards
# backwards: print input in backward line order
awk ' { line[NR] = $0 }
END { for (i = NR; i > 0; i--) print line[i] } ' $*
$
Заметьте, что подобно переменным, массивы не нужно описывать; размер массива ограничен только объемом памяти, доступным на вашей машине. Конечно, если очень большой файл заносится в массив, в конце концов, это может привести к исчерпанию ресурсов памяти. Для печати конца большого файла в обратном порядке следует обратиться за помощью к команде tail
:
$ tail -5 /usr/dict/web2 | backwards
zymurgy
zymotically
zymotic
zymosthenic
zymosis
$
Команда tail
использует возможности файловой системы — операцию "поиск" (seeking), позволяющую перейти к концу файла без чтения всей предшествующей информации. Подробнее эта операция будет рассмотрена при обсуждении функции lseek
в гл. 7. (В нашей команде tail
есть флаг -r
, который определяет печать строк в обратном порядке, заменяя команду backwards
).
При обычной обработке входная строка разбивается на поля. Эту операцию можно выполнить с помощью встроенной функции split
над любой строкой:
n = split(s, arr, sep)
Строка s
разбивается на поля, записываемые в элементы массива arr
от 1 до n
. Используется символ разделения полей sep
, если он задан; в противном случае применяется текущее значение переменной FS
. Например, обращение split($0, а, ":")
разбивает входную строку на столбцы, что подходит для обработки файла /etc/passwd
, поэтому обращение split("9/29/83", date, "/")
разбивает дату по символам дробной черты.
$ sed 1q /etc/passwd | awk '{split($0, a, ":"); print a[1]}'
root
$ echo 9/29/83 | awk '{split($0, date, "/"); print date[3]}'
83
$
В табл. 4.5 перечислены встроенные функции awk
.
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии