Литмир - Электронная Библиотека
Содержание  
A
A

$ cat double

awk '

FILENAME != prevfile { # new file

 NR = 1                # reset line number

 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
.

cos(expr)
Косинус
expr
exp(expr)
Возведение в степень
expr
getline()
Чтение следующей входной строки; возвращает 0 в случае конца файла, в противном случае 1
index(s1, s2)
Положение строки
s2
в
s1
; возвращает 0, если строка не входит
int(expr)
Целая часть
expr
; округляет по минимуму
length(s)
Длина строки
s
log(expr)
Натуральный логарифм
expr
sin(expr)
Синус
expr
split(s, a, c)
Разбиение
s
на
а[1]
...
a[n]
по символу
c
; возвращает
n
sprintf(fmt, ...)
Форматирование в соответствии со спецификацией
fmt
substr(s,m,n)
Подстрока в
n
символов строки
s
, начинающаяся с индекса
m
53
{"b":"248117","o":1}