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

Sharpeners

5

1

Наша задача заключается в просмотре значения и уточнении, какие пункты следует заказать повторно. Если требуется повторный заказ, нужно дважды его выполнить для данного пункта. Выводной поток данных также должен сообщить, какое количество пунктов нужно заказать повторно, и, кроме того, уточнить общее количество повторных заказов.

Ранее уже рассматривалось, каким образом можно игнорировать строки, начинающиеся определенными символами. Сначала производится чтение из файла. При этом игнорируются все строки, которые начинаются символами # и строками вида "ITEM". После прочтения осуществляется перенаправление данных во временный файл. Затем команда sed применяется для удаления пустых строк. На самом деле все, что делается в этом случае, напоминает фильтрацию текстового файла. Описанные действия реализованы с помощью следующего кода.

$ pg whileorder

#!/bin/sh

# whileorder

INPUT_FILE=order

HOLD=order.tmp

if [ -s $INPUT_FILE ]; then

# пустой файл вывода, добавление не производится!

>$HOLD

while read LINE

do

case $LINE in

\#*|ITEM*) ;; # игнорирование строк, содержащих символы # или ITEM

*)

# перенаправление вывода во временный файл

echo $LINE >$HOLD

;;

esac

done <$INPUT_FILE

# применение команды sed для удаления пустых строк

sed -e '/^$/d' order.tmp > order.$$

mv order.$$ order.tmp

else

echo "`basename $0` : Sorry $INPUT_FILE does not exist or ls empty"

fi

В результате выполнения сценария получаем следующее:

$ pg order.tmp

Pens 14 12

Pencils 15 15

Pads 7 3

Disks 3 2

Sharpeners 5 1

Теперь остается только выполнить считывание временного файла в другом цикле while, а затем реализовать некоторые сравнения с помощью команды expr. Вот соответствующий сценарий:

$ pg whileorder2

#!/bin/sh

#whileorder2

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

HOLD=order.tmp

RE_ORDER=0

ORDERS=0

STATIONERY_TOT=0

if [ -s $HOLD ]; then

echo "=========== STOCK RE_ORDER REPORT ================"

while read ITEM REORD LEVEL

do

#находимся ли мы ниже уровня переупорядочивания для данного пункта??

if [ "$LEVEL" — lt "$REORD" ]; then

да, выполняется заказ другого количества товаров

NEW_ORDER=`expr $REORD + $REORD`

# подсчет итогов по заказам

ORDERS=`expr $ORDERS + 1`

# подсчет итогов по уровням запасов

STATIONERY_TOT=`expr $STATIQNERY_TOT + $LEVEL`

echo "$ITEM need reordering to the amount $NEW_ORDER"

done <$HOLD

echo "$ORDERS new items need to be ordered"

echo "Our reorder total ls $STATIONERY_TOT"

else

echo "`basename $0` : Sorry $HOLD does not exist or ls empty"

fi

Результат выполнения сценария при обработке файла заказов.

$ whileorder

========= STOCK REORDER REPORT ===============

Pens need reordering to the amount 28

Pads need reordering to the amount 14

Disks need reordering to the amount 6

Sharpeners need reordering to the amount 10

4 new items need to be ordered

Our reorder total is 18

Не составляет особого труда скомбинировать два описанных сценария в один; в действительности изначально использовался один сценарий, который был разбит на два в учебных целях.

18.7.10. Цикл while и дескрипторы файлов

При изучении дескрипторов файлов в главе 5 уже упоминалось о том, что для считывания данных в файл применяется цикл while. С помощью дескрипторов файлов 3 и 4 следующий сценарий создает резервную копию файла myfile.txt под именем myfile.bak. Обратите внимание, что в начале сценария осуществляется проверка, которая позволяет убедиться в наличии файла. Если файл отсутствует или не содержит данные, выполнение сценария немедленно прекращается. Также обратите внимание на то, что в цикле while имеется команда null (:). Из‑за наличия этой команды цикл может выполняться бесконечно, поскольку null всегда возвращает значение "истина". При осуществлении попытки считывания по достижении конца файла отображается сообщение об ошибке. При этом выполнение сценария прекращается.

$ pg copyfile

#!/bin/sh

# copyfile

FILENAME=myfile.txt

FILENAME_BAK=myfile.bak

if [ -s $FILENAME ]; then

#открыть FILENAME для записи

#открыть FILENAME для считывания'

exec 4>$FILENAME_BAK

exec 3<$FILENAME

#бесконечный цикл до тех пор, пока имеются данные или пока не возникает

#ошибка, связанная с достижением конца файла while :

do

read LINE <&3

if [ "$?" -ne 0 ]; then

# ошибки при закрытии

exec 3<&-

exec 4<&-

exit fi

# запись в файл FILENAME_BAK

echo $LINE>&4

done else

echo "`basename $0` : Sorry, $FILENAME is not present or is empty" >&2

fi

18.8. Управление ходом выполнения циклов с помощью команд break и continue

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

   • break;

   • continue.

18.8.1. Команда break

Команда break позволяет прервать выполнение цикла. Эта команда обычно'; используются для выхода из цикла или прекращения выполнения оператора case' после осуществления некоторой обработки. Если вы окажетесь внутри вложенного цикла, можно указать количество прерываемых циклов: например, если существуют два вложенных цикла, для их прерывания используется команда break 2.

18.8.2. Прекращение выполнения оператора case

Рассмотрим следующий пример. В сценарии выполняется бесконечный цикл до тех пор, пока пользователь не введет число, большее 5. Для прерывания цикла и возврата в командную строку интерпретатора используется команда break.

$ pg breakout

#!/bin/sh

   • breakout

   • while : бесконечный цикл while :

do

echo -n "Enter any number [1..5] :"

read ANS

case $ANS in

1|2|3|4|5) echo "great you entered a number between 1 and 5"

;;

*) echo "Wrong number..bye"

break

;;

esac

done

18.8.3. Команда continue

Команда continue по своему действию напоминает команду break, за исключением одной существенной детали: она не прерывает цикл, а лишь приводит к пропуску текущей итерации цикла.

18.8.4. Пропуск строк в файлах

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

$ pg names2.txt

LISTING OF PERSONNEL FILE

TAKEN AS AT 06/1999

Louise Conrad:Accounts:ACC8987

Peter James:Payroll:PR489

Fred Terms:Customer:CUS012

Janes Lenod:Accounts:ACC887

Frank Pavely:Payroll:PR4S9

При просмотре этого файла нетрудно заметить, что его первые две строки не содержат сведений о сотрудниках. Поэтому эти строки желательно исключить.

Также не следует принимать во внимание сведения о сотруднике с именем Peter

james Этот человек уволился из компании, но запись о нем осталась в файле.

Давайте все же сохраним заголовочную информацию, выполнив простой подсчет считываемых строк При этом обработка файла будет выполняться в том случае, когда номер строки будет больше двух Если строка содержит имя Peter James, она будет исключена из процесса обработки.

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