Искусство программирования на языке сценариев командной оболочки
Шрифт:
#!/bin/bash
echo "uninitialized_var = $uninitialized_var"
# uninitialized_var =
Часто программисты путают операторы сравнения = и – eq. Запомните, оператор = используется для сравнения строковых переменных, а – eq– - для сравнения целых чисел.
if [ "$a" = 273 ] # Как вы полагаете? $a -- это целое число или строка?
if [ "$a" -eq 273 ] # Если $a -- целое число.
# Иногда,
# Однако...
a=273.0 # Не целое число.
if [ "$a" = 273 ]
then
echo "Равны."
else
echo "Не равны."
fi # Не равны.
# тоже самое и для a=" 273" и a="0273".
# Подобные проблемы возникают при использовании "-eq" со строковыми значениями.
if [ "$a" -eq 273.0 ]
then
echo "a = $a'
fi # Исполнение сценария прерывается по ошибке.
# test.sh: [: 273.0: integer expression expected
Ошибки при сравнении целых чисел и строковых значений.
#!/bin/bash
# bad-op.sh
number=1
while [ "$number" < 5 ] # Неверно! должно быть while [ "number" -lt 5 ]
do
echo -n "$number "
let "number += 1"
done
# Этот сценарий генерирует сообщение об ошибке:
# bad-op.sh: 5: No such file or directory
Иногда, в операциях проверки, с использованием квадратных скобок ([ ]), переменные необходимо брать в двойные кавычки. См. Пример 7-6, Пример 16-4 и Пример 9-6.
Иногда сценарий не в состоянии выполнить команду из-за нехватки прав доступа. Если пользователь не сможет запустить команду из командной строки, то эта команда не сможет быть запущена и из сценария. Попробуйте изменить атрибуты команды, возможно вам придется установить бит suid.
Использование символа – в качестве оператора перенаправления (каковым он не является) может приводить к неожиданным результатам.
command1 2> - | command2 # Попытка передать сообщения об ошибках команде command1 через конвейер...
# ...не будет работать.
command1 2>& - | command2 # Так же бессмысленно.
Спасибо S.C.
Использование функциональных особенностей Bash версии 2 или выше, может привести к аварийному завершению сценария, работающему под управлением Bash версии 1.XX.
#!/bin/bash
minimum_version=2
# Поскольку Chet Ramey постоянно развивает Bash,
# вам может потребоваться указать другую минимально допустимую версию $minimum_version=2.XX.
E_BAD_VERSION=80
if [ "$BASH_VERSION" \< "$minimum_version" ]
then
echo "Этот сценарий должен исполняться под управлением Bash, версии $minimum или выше."
echo "Настоятельно рекомендуется обновиться."
exit $E_BAD_VERSION
fi
...
Использование специфических особенностей Bash может приводить к аварийному завершению сценария в Bourne shell (#!/bin/sh).
Как правило, в Linux дистрибутивах, sh является псевдонимом bash, но это не всегда верно для UNIX-систем вообще.Сценарий, в котором строки отделяются друг от друга в стиле MS-DOS (\r\n), будет завершаться аварийно, поскольку комбинация #!/bin/bash\r\n считается недопустимой. Исправить эту ошибку можно простым удалением символа \r из сценария.
#!/bin/bash
echo "Начало"
unix2dos $0 # Сценарий переводит символы перевода строки в формат DOS.
chmod 755 $0 # Восстановление прав на запуск.
# Команда 'unix2dos' удалит право на запуск из атрибутов файла.
./$0 # Попытка запустить себя самого.
# Но это не сработает из-за того, что теперь строки отделяются
# друг от друга в стиле DOS.
echo "Конец"
exit 0
Сценарий, начинающийся с #!/bin/sh, не может работать в режиме полной совместимости с Bash. Некоторые из специфических функций, присущих Bash, могут оказаться запрещенными к использованию. Сценарий, который требует полного доступа ко всем расширениям, имеющимся в Bash, должен начинаться строкой #!/bin/bash.
Сценарий не может экспортировать переменные родительскому процессу - оболочке. Здесь как в природе, потомок может унаследовать черты родителя, но не наооборот.
WHATEVER=/home/bozo
export WHATEVER
exit 0
bash$ echo $WHATEVER
bash$
Будьте уверены -- при выходе в командную строку переменная $WHATEVER останется неинициализированной.
Использование в подоболочке переменных с теми же именами, что и в родительской оболочке может не давать ожидаемого результата.
Пример 31-1. Западня в подоболочке
#!/bin/bash
# Западня в подоболочке.
outer_variable=внешняя_переменная
echo
echo "outer_variable = $outer_variable"
echo
(
# Запуск в подоболочке
echo "внутри подоболочки outer_variable = $outer_variable"
inner_variable=внутренняя_переменная # Инициализировать
echo "внутри подоболочки inner_variable = $inner_variable"
outer_variable=внутренняя_переменная # Как думаете? Изменит внешнюю переменную?
echo "внутри подоболочки outer_variable = $outer_variable"
# Выход из подоболочки
)
echo
echo "за пределами подоболочки inner_variable = $inner_variable" # Ничего не выводится.
echo "за пределами подоболочки outer_variable = $outer_variable" # внешняя_переменная.
echo
exit 0
Передача вывода от echo по конвейеру команде read может давать неожиданные результаты. В этом сценарии, команда read действует так, как будто бы она была запущена в подоболочке. Вместо нее лучше использовать команду set (см. Пример 11-14).