Mir-knigi.online
Книги онлайн читать бесплатно!
  • Главная
  • Жанры
  • ТОП книг
  • ТОП авторов
  • Контакты

Командная строка Linux

Часть 98 из 113 Информация о книге

./trouble: строка 9: `else'

И снова сообщение об ошибке указывает на место, расположенное гораздо дальше фактического места ошибки. Здесь складывается очень интересная ситуация. Как вы помните, if принимает список команд и проверяет код завершения последней команды в списке. В нашей программе мы задумали список с единственной коман­дой [, которая является синонимом команды test. Команда [ принимает все, что следует за ней, как список аргументов — в данном случае четыре аргумента: $number, =, 1 и ]. В отсутствие точки с запятой в список аргументов будет добавлено слово then, что синтаксически допустимо. Следующая команда echo также допустима. Она интерпретируется как еще одна команда в списке команд, которую if должна выполнить и проверить код завершения. Далее следует неуместное здесь слово else, потому что командная оболочка распознает его как зарезервированное слово (слово, имеющее специальное значение для командной оболочки), а не как имя команды. Это объясняет смысл сообщения об ошибке.

Непредвиденная подстановка

Существуют ошибки, которые возникают лишь время от времени. Иногда сценарий работает без ошибок, а иногда терпит неудачу из-за работы механизма подстановки. Для демонстрации этой проблемы вернем точку с запятой на место и изменим значение переменной number, присвоив ей пустое значение:

#!/bin/bash

# trouble: сценарий для демонстрации распространенных видов ошибок

number=

if [ $number = 1 ]; then

        echo "Number is equal to 1."

else

        echo "Number is not equal to 1."

fi

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

[[email protected] ~]$ trouble

./trouble: строка 7: [: =: ожидается использование унарного оператора

Number is not equal to 1.

Мы получили довольно загадочное сообщение, за которым следует вывод второй команды echo. Проблема заключается в подстановке переменной number в команду test. После обработки команды

[ $number = 1 ]

механизмом подстановки, который заменит number пустым значением:

[ = 1 ]

получится недопустимый результат, и командная оболочка сгенерирует сообщение об ошибке. Оператор = является бинарным (он требует наличия двух операндов, по одному с каждой стороны), но первое значение отсутствует, поэтому коман­да test ожидает встретить унарный оператор (такой, как -z). Далее, поскольку test вернула ненулевой код завершения (из-за ошибки), команда if получит ненулевой код завершения, примет соответствующее решение и выполнит вторую команду echo.

Эту проблему можно исправить, заключив в кавычки первый аргумент команды test:

[ "$number" = 1 ]

Теперь подстановка приведет к следующему результату:

[ "" = 1 ]

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

Логические ошибки

Логические ошибки, в отличие от синтаксических, не прерывают выполнение сценария. Сценарий работает, но желаемых результатов вы не дождетесь, и причина этому — проблемы с логикой. Существует бесчисленное множество возможных логических ошибок, ниже перечислены наиболее типичные их виды, встречающиеся в сценариях:

• Неправильное условное выражение. Очень легко неправильно запрограммировать оператор if/then/else и получить ошибочную логику работы. Иногда логика получается полностью обратной желаемой или не охватывает весь возможный набор ситуаций.

• Ошибки «смещения на единицу». При программировании циклов со счетчиками можно упустить из виду, что цикл должен начинать считать с 0, а не с 1, чтобы счет закончился в нужной точке. Ошибки этого вида приводят к тому, что цикл выполняет на одну итерацию больше или меньше, заканчиваясь соответственно слишком поздно или слишком рано.

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

Защитное программирование

При программировании важно не опираться на допущения, то есть тщательно проверять коды завершения программ и команд, используемых сценарием. Вот пример из реальной жизни. Системный горе-администратор написал сценарий, выполняющий некую административную задачу на очень важном сервере. Этот сценарий содержал следующие две строки кода:

cd $dir_name

rm *

В самих строках нет никакой ошибки, при условии, что каталог, указанный в переменной dir_name, действительно существует. Но что случится, если это не так? Тогда команда cd потерпит неудачу, сценарий перейдет к следующей строке и удалит файлы в текущем рабочем каталоге. Результат, как вы понимаете, далек от ожидаемого! Несчастный администратор уничтожил массу важных файлов на сервере из-за этой логической ошибки.

Рассмотрим несколько способов усовершенствования описанной логики. Прежде всего, можно поставить вызов команды rm в зависимость от успеха cd:

cd $dir_name && rm *

В этом случае, если команда cd потерпит неудачу, команда rm не будет выполнена. Так намного лучше, но еще остается вероятность отсутствия переменной dir_name или хранения в ней пустого значения, что, безусловно, приведет к удалению файлов в домашнем каталоге пользователя. Этого можно избежать, убедившись, что dir_name действительно содержит имя существующего каталога:

[[ -d $dir_name ]] && cd $dir_name && rm *

В подобных ситуациях, как описанных выше, лучше прервать выполнение сценария с выводом сообщения об ошибке:

if [[ -d $dir_name ]]; then

        if cd $dir_name; then

                rm *

        else

                echo "cannot cd to '$dir_name'" >&2

                exit 1

        fi

else

        echo "no such directory: '$dir_name'" >&2

        exit 1

fi

Здесь проверяются существование каталога с указанным именем и успешное завершение команды cd. Если какая-то из проверок завершается неудачей, в стандартный вывод ошибок отправляется содержательное описание и сценарий завершается с кодом 1, чтобы показать, что он завершился с ошибкой.

Проверка ввода

Главное правило надежного программирования: если программа принимает ввод, она должна уметь обработать все, что ей передали. Обычно это означает тщательную отбраковку ввода с целью гарантировать, что дальнейшей обработке будут подвергнуты только допустимые данные. Пример такой проверки мы видели в предыдущей главе, когда обсуждали команду read. Там один из сценариев содержал следующую проверку выбранного пункта меню:

[[ $REPLY =~ ^[0-3]$ ]]

удачный дизайн есть функция от времени

Когда я в студенчестве изучал промышленное проектирование, мудрый профессор учил нас, что степень проработки проекта определяется объемом времени, выделенного проектировщику. Если вам дано 5 минут на проектирование устройства для уничтожения воздушных целей, вы спроектируете мухобойку. А если срок — 5 месяцев, вы сможете спроектировать лазерную систему противовоздушной обороны.

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


Перейти к странице:
Предыдущая страница
Следующая страница
Жанры
  • Военное дело
  • Деловая литература
  • Детективы и триллеры
  • Детские
  • Детские книги
  • Документальная литература
  • Дом и дача
  • Дом и Семья
  • Жанр не определен
  • Зарубежная литература
  • Знания и навыки
  • История
  • Компьютеры и Интернет
  • Легкое чтение
  • Любовные романы
  • Научно-образовательная
  • Образование
  • Поэзия и драматургия
  • Приключения
  • Проза
  • Прочее
  • Психология и мотивация
  • Публицистика и периодические издания
  • Религия и духовность
  • Родителям
  • Серьезное чтение
  • Спорт, здоровье и красота
  • Справочная литература
  • Старинная литература
  • Техника
  • Фантастика и фентези
  • Фольклор
  • Хобби и досуг
  • Юмор
Mir-knigi.online

Бесплатная онлайн библиотека для чтения книг без регистрации с телефона или компьютера. У нас собраны последние новинки, мировые бестселлеры книжного мира.

Контакты
  • [email protected]
Информация
  • Карта сайта
© mir-knigi.online, 2026. | Вход