Ранее уже рассматривалось, каким образом можно игнорировать строки, начинающиеся определенными символами. Сначала производится чтение из файла. При этом игнорируются все строки, которые начинаются символами # и строками вида "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