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

do

echo "Filesystem..logs ls nearly full" | mail root

done

exit 0

18.7. Цикл while

Цикл while выполняет ряд команд до тех пор, пока истинно условие. Этот цикл используется также для просмотра данных из файла ввода. Формат цикла while:

while команда

do

команды1

команды2

done

Между конструкциями while и do находится несколько команд, хотя в общем случае применяется только одна команда. Обычно команда выполняет проверку условия.

Команды, размещенные между ключевыми словами do и done, выполняются только в том случае, если код завершения command равен нулю; если код завершения принимает какое‑либо другое значение, цикл заканчивается.

Когда команды выполнены, контроль передается обратно, в верхнюю часть цикла. И все начинается снова до тех пор, пока проверяемое условие отлично от нуля.

18.7.1. Простой цикл while

Ниже приводится основная форма цикла while. Условие тестирования состоит в том, что если "COUNTER is less than 5", условие останется истинным. Переменная counter имеет начальное значение нуль, и ее значение увеличивается на постоянную величину при выполнении цикла.

$ pg whilecount

#!/bin/sh # whilecount COUNTER=0

#счетчик равен 5?

while [ $COUNTER -lt 5 ] do

#прибавление к счетчику единицы

COUNTER=`expr $COUNTER + 1`

echo $COUNTER

done

Указанный сценарий выводит на экран числа от 1 до 5, затем завершает работу.

$ whilecount

1 2 3

4

5

18.7.2. Применение цикла while при вводе с клавиатуры

Цикл while может применяться для ввода информации с клавиатуры. В следующем примере введенная информация присваивается переменной film. Если нажать клавиши [Ctrl+D], цикл завершает выполнение.

$ pg whileread

#!/bin/sh

# whileread

echo " type <CTRL‑D> to terminate"

echo -n "enter your most liked film :"

while read FILM

do

echo "Yeah, great film the $FILM"

done

Когда сценарий выполняется, вводимыми данными могут быть:

$ whileread

enter your most liked film: Sound of Music

Yeah, great film the Sound of Music

<CTRL‑D>

18.7.3. Применения цикла while для считывания данных из файлов

Обычно цикл while используется для считывания данных из файла, что позволяет сценарию обрабатывать информацию.

Предположим, что следует просмотреть информацию из следующего персонального файла, содержащего имена служащих, их ID и названия отделов.

$ pg names.txt

Louise Conrad:Accounts:ACC8987

Peter James:Payroll:PR489

Fred Terms:Customer:CUS012

James Lenod:Accounts:ACC887

Frank Pavely:Payroll:PR489

Для хранения строк данных можно использовать переменные. Условие истинно до тех пор, пока не считываются новые данные. Для просмотра содержимого файла цикл while использует перенаправление потока данных ввода. Обратите внимание, что отдельной переменной $LINE присваивается целая строка.

$ pg whileread

#!/bin/sh

# whileread

while read LINE

do

echo $LINE

done < names.txt

$ whileread

Louise Conrad:Accounts:ACC8987

Peter James:Payroll:PR489

Fred Terras:Customer:CUS012

James Lenod:Accounts:ACC887

Frank Pavelу:Payroll:PR4 8 9

18.7.4. Считывание данных из файлов с помощью IFS

Чтобы при выводе данных устранить разделитель полей в виде двоеточия, примените переменную ifs, предварительно сохранив ее установки. После того как сценарий завершит работу с этими установками, восстановите установки переменной ifs. С помощью переменной ifs можно изменить разделитель полей на двоеточие вместо пробела или символа табуляции, которые заданы по умолчанию. Как известно, отдельной переменной можно присвоить значения трех полей: NAME, dept и id.

Чтобы улучшить внешний вид записей, немного увеличивая поля, можно с помощью команды echo применить символы табуляции. Рассмотрим сценарий:

$ pg whilereadifs

#!/bin/sh

#whilereadifs

#сохраните установку IFS

SAVEDIFS=$IFS

#присвоим переменной IFS новый разделитель

IFS=:

while read NAME DEPT ID

do

echo -e "$NAME\t $DEPT\t $ID" done < names.txt

# восстановим установки переменнойIFS

IFS=$SAVEDIFS

При выполнении сценария получим более привлекательный поток вывода:

$ whilereadifs

Louise Conrad Accounts ACC8987

Peter James Payroll PR489

Fred Terms Customer CUS012

James Lenod Accounts ACC887

Frank Pavely Payroll PR489

18.7.5. Обработка файла с помощью проверок условий

Большинство циклов while включает некоторый оператор проверки, который уточняет последовательность действий.

Ниже рассматривается файл с именами служащих, и на экран выводятся подробности. После обнаружения имени служащего "James Lenod" сценарий завершает работу. Вывод на экран подробностей до осуществления проверки позволяет удостовериться, что "James Lenod" добавляется в содержимое файла.

Обратите внимание, что все переменные задаются в начале сценария. При внесении небольших поправок в переменные можно сэкономить рабочее время и

сократить количество типов. Все редакторские правки находятся в начале, а не рассеяны по всему сценарию.

$ pg whileread_file

#!/bin/sh

#whileread_file

#инициализация переменных

SAVEDIFS=$IFS

IFS=:

HOLD_FILE=hold_file

NAME_MATCH="James Lenod"

INPUT_FILE=names.txt

# создавайте каждый раз новый HOLD_FILE, в случае, когда сценарий

непрерывно выполняется

>$HOLD FILE

while read NAME DEPT ID

do

#выводит на экран всю информацию в holdfile с помощью перенаправления

echo $NAME $DEPT $ID >>$HOLD_FILE

#имеется ли соответствие ???

if [ "$NAME"="$NAME_MATCH" ]; then

# да, тогда удобно завершить работу

echo "all entries up to and including $NAME_MATCH are in $HOLD_FILE"

exit 0

fi

done < $INPUT_FILE

# восстановление IFS

IFS=$SAVEDIFS

Выполним следующий шаг и уточним количество служащих в каждом из отделов. Сохраним прежний формат просмотра, в котором каждому полю присваивается название переменной. Затем для добавления каждого совпадения с помощью оператора case просто применим команду expr. Если обнаруживается неизвестный отдел, его название выводится на экран в виде стандартного потока ошибок; поэтому, если отдел не существует, нет необходимости прерывать выполнение сценария.

$ pg whileread_cond

#!/bin/sh

# whileread_cond

# инициализация переменных ACC_LOOP=0; CUS_LOOP=0; PAY_LOOP=0;

SAVEDIFS=$IFS

IFS=:

while read NAME DEPT ID

do

# счетчик увеличивается на единицу для каждого совпадающего названия отдела.

case $DEPT in

Accounts)

ACC_LOOP=`expr $ACC_LOOP + 1`

ACC="Accounts"

;;

Customer)

CUS_LOOP=`expr SCUS_LOOP + 1`

CUS="Customer"

;;

Payroll)

PAY_LOOP=`expr $PAY_LOOP + 1`

PAY="Pay roll"

;;

*) echo "`basename $0`: Unknown department $DEPT" >&2

;;

esac

done < names.txt

IFS=$SAVEDIFS

echo "there are $ACC_ LOOP employees assigned to $ACC dept"

echo "there are $CUS_LOOP employees assigned to $CUS dept"

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