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

   2. Предыдущая командная строка передается новой командной строке в качестве аргумента.

В нашем случае это означает, что при запуске сценария вместо команды

$ student_tot.awk grade.txt

в действительности выполняется такая команда:

$ /bin/awk -f student_tot.awk grade.txt

Опция -f утилиты awk говорит о том, что выполняемые команды находятся в указанном вслед за ней файле.

После создания файл student_tot.awk необходимо сделать исполняемым с помощью команды

$ chmod u+x student_tot.awk

Вот результаты работы сценария:

$ student_tot.awk grade.txt

Student name

Date joined

Member number

Grade

Age

Points gained

Max

point available

M. Tansley

05/99

18311

Green

8

40

44

J. Lulu

06/99

48317

green

9

24

26

P. Bunny

02/99

48

Yellow

12

35

28

J. Troll

07/99

4842

Brown-3

12

26

26

L. Tansley

05/99

4712

Brown~2

12

30

28

Club student

total points: 155

Average Club

Student

points: 31

Использование переменной FS в сценариях awk

Если просматривается файл, в котором разделителем полей является символ, отличный от пробела, например '#' или ':', это легко учесть, указав в командной строке опцию ' -F:'

$ awk -F: '{print $0}' входной_файл

Аналогичную функцию выполняет переменная FS, которую можно установить непосредственно в сценарии. Следующий сценарий обрабатывает файл /etc/passwd, выводя на экран содержимое первого и пятого полей, включающих соответственно имя пользователя и описание роли пользователя в системе. Поля в этом файле разделены символом двоеточия, поэтому в процедурной части шаблона begin устанавливается переменная FS, значение которой заключается в двойные кавычки:

$ cat passwd.awk

#!/bin/awk -f

# Имя файла: student_tot.awk

# Командная строка: passwd.awk /etc/passwd

# Вывод содержимого первого и пятого полей файла паролей.

BEGIN {

FS=":" }

{print $1"\t"$5}

Вот возможные результаты работы этого сценария:

$ passwd.awk /etc/passwd

root Special Admin login

xdm Restart xda Login

sysadm Regular Admin login

daemon Daemon Login for daemons needing permissions

Передача переменных сценариям awk

При передаче переменной сценарию awk формат командной строки таков:

awk файл_сценария переменная=значение входной_файл

Следующий небольшой сценарий сравнивает количество полей в каждой записи входного файла с заданным в командной строке значением. Текущее количество полей хранится в переменной NF. Сравниваемое значение передается сценарию в виде переменной МАХ.

$ cat fieldcheck.awk

#!/bin/awk -f

#Имя файла: fieldcheck.awk

#Командная строка: fieldcheck.awk MAX=n [FS=<разделитель>] имя_файла

#Проверка числа полей в записях файла.

{if(NF != МАХ)

print "line " NR " does not have " MAX " fields"}

При запуске этого сценария вместе с файлом /etc/passwd, содержащим семь полей, необходимо указать следующие параметры:

$ fieldcheck.awk МАХ=7 FS=":" /etc/passwd

Следующий сценарий выводит информацию об учениках, чей возраст ниже значения, заданного в командной строке:

$ cat age.awk

#!/bin/awk -f

# Имя файла: age.awk

# Командная строка: age.awk AGE=n grade.txt

# Вывод информации об учениках, чей возраст ниже заданного,

{if($5 < AGE) print $0}

$ age.awk AGE=10 grade.txt

M. Tansley 05/99 48311 Green В 4 0 4 4 J. Lulu 06/99 18317 green 9 24 26

9.2.15. Массивы

Изучая функцию split(), мы говорили о том, каким образом ее можно использовать для преобразования строки символов в массив. Повторим соответствующий пример:

$ awk 'BEGIN {print split("123#456#678", myarray, "#")}'

3

Функция split() возвращает число элементов созданного массива myarray. Внутренняя структура массива myarray в этом случае такова:

myarray[1]="123" myаrray[2]="456" myarray[3]="678"

При работе с массивами в awk не требуется заранее их объявлять. Не нужно также указывать количество элементов массива. Для доступа к массиву обычно применяется цикл for, синтаксис которого следующий:

for (элемент in массив) print массив[элемент]

В показанном ниже сценарии функция split() разбивает заданную строку на элементы и записывает их в массив myarray, а в цикле for содержимое массива выводится на экран:

$ cat arraytest.awk

#! /bin/awk -f

#Имя файла: arraytest.awk

#Командная строка: arraytest.awk /dev/null

#Вывод элементов массива.

BEGIN {

record="l23#456#789";

split(record, myarray, "#") } END {

for (i in myarray) print myarray[i]

}

Для запуска сценария в качестве входного файла следует указать устройство /dev/null. Если этого не сделать, утилита awk будет ожидать поступления данных с клавиатуры.

$ arraytest.awk /dev/null

123

789

Статические массивы

В предыдущем примере массив формировался динамически. Следующий пример является более сложным и демонстрирует, как создавать в сценарии статические массивы. Ниже показан входной файл grade_student.txt, включающий информацию об учениках нашей секции каратистов. Записи файла содержат два поля: первое — название пояса, которым владеет ученик, второе — категория ученика (взрослый, юниор). Разделителем полей служит символ '#'.

$ cat grade_student.txt

Vellow#Junior

Orange#Senior

Yellow#Junior

Purple#Junior

Brown-2#Junior

White#Senior

Drange#Senior

Red#Junior

Brown-2#Senior

Yellow#Senior

Red#Junior

Blue#Senior

Green#Senior

Purple#Junior

White#Junior .

Наша задача заключается в том, чтобы прочитать файл и получить следующие сведения:

   1. Сколько учеников имеют желтый, оранжевый и красный пояса?

   2. Сколько взрослых и детей посещают секцию? Рассмотрим такой сценарий:

$ cat belts.awk

#!/bin/awk -f

#Имя файла: belts.awk

#Командная строка: belts.awk grade_student.txt

#Подсчет числа учеников, имеющих желтый, оранжевый и красный пояса,

#а также количества взрослых и юных членов секции.

# Задание разделителя и создание массивов.

BEGIN (

FS="#"

# Создание массива, индексами которого являются

#названия поясов. belt["Yellow"] belt["Orange"] belt["Red"]

#Создание массива, индексами которого являются

#названия категорий учеников. student["Junior"]

student["Senior"]

}

#Если значение первого поля совпадает с индексом массива belt,

#содержимое соответствующего элемента массива увеличивается на единицу. {for(colour in belt)

{if ($1==colour)

belt[colour]++ ) }

# Если значение второго поля совпадает с индексом массива student,

# содержимое соответствующего элемента массива увеличивается на единицу, { for (senior_or_junior in student) { if ($2==senior_or_junior)

student [senior_or_junior] ++

) }

# Вывод полученных результатов

END {

for (colour in belt)

print "The club has", belt[colour], colour, "belts" for(senior_or_junior in student)

32
{"b":"273485","o":1}