Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание - страница 16
Код
Листинг 1.9. Сценарий validint
>#!/bin/bash
># validint — Проверяет целые числа, поддерживает отрицательные значения
>validint()
>{
>··# Проверяет первое значение и сравнивает с минимальным значением $2 и/или
>··#·· с максимальным значением $3, если они заданы. Если проверяемое значение
>··#·· вне заданного диапазона или не является допустимым целым числом,
>··#·· возвращается признак ошибки.
>··number="$1"; min="$2"; max="$3"
>
>····echo "You didn't enter anything. Please enter a number." >&2
>····return 1
>··fi
>··# Первый символ — знак "минус"?
>
>····testvalue="${number#?}" # Оставить для проверки все, кроме первого символа
>··else
>····testvalue="$number"
>··fi
>··# Удалить все цифры из числа для проверки.
>
>··# Проверить наличие нецифровых символов.
>··if [! -z $nodigits]; then
>····echo "Invalid number format! Only digits, no commas, spaces, etc." >&2
>····return 1
>··fi
>
>····# Входное значение меньше минимального?
>····if ["$number" −lt "$min"]; then
>······echo "Your value is too small: smallest acceptable value is $min." >&2
>······return 1
>····fi
>··fi
>··if [! -z $max]; then
>····# Входное значение больше максимального?
>····if ["$number" −gt "$max"]; then
>······echo "Your value is too big: largest acceptable value is $max." >&2
>······return 1
>····fi
>··fi
>··return 0
>}
Как это работает
Проверка целочисленных значений реализуется очень просто благодаря тому что такие значения состоят исключительно из последовательности цифр (от 0 до 9), перед которой может находиться единственный знак «минус». Если в вызов функции validint() передать минимальное и (или) максимальное значение, она также проверит вхождение заданного значения в указанный диапазон.
Сначала функция проверяет ввод непустого значения
Если введенное значение допустимо, оно сравнивается с минимальным и максимальным значениями
Запуск сценария
Весь сценарий целиком является функцией. Его можно скопировать в другой сценарий или подключить как библиотечный файл. Чтобы преобразовать его в команду, просто добавьте в конец файла код из листинга 1.10.
Листинг 1.10. Дополнительная поддержка, превращающая сценарий в самостоятельную команду
># Проверка ввода
>if validint "$1" "$2" "$3"; then
>····echo "Input is a valid integer within your constraints."
>fi
Результаты
После добавления кода из листинга 1.10, сценарий можно использовать, как показано в листинге 1.11:
Листинг 1.11. Тестирование сценария validint
>$ validint 1234.3
>Invalid number format! Only digits, no commas, spaces, etc.
>$ validint 103 1 100
>Your value is too big: largest acceptable value is 100.
>$ validint -17 0 25
>Your value is too small: smallest acceptable value is 0.
>$ validint -17 -20 25
>Input is a valid integer within your constraints.
Усовершенствование сценария
Обратите внимание на строку
>if ["${number%${number#?}}" = "-"]; then
Если первый символ действительно является знаком «минус», переменной testvalue присваивается числовая часть значения. Затем из этого неотрицательного значения удаляются все цифры и выполняется следующая проверка.
В данном случае велик соблазн использовать логический оператор И (-a), чтобы объединить выражения и избавиться от вложенных инструкций if. Например, на первый взгляд кажется, что следующий код должен работать:
>if [! -z $min −a "$number" −lt "$min"]; then
>··echo "Your value is too small: smallest acceptable value is $min." >&2
>··exit 1
>fi
Но он не работает, потому что, даже если первое выражение, слева от оператора И, вернет ложное значение, нет никаких гарантий, что вторая проверка не будет выполнена (хотя в большинстве других языков программирования получилось бы именно так). То есть вы рискуете столкнуться со множеством ошибок из-за сравнения недействительных или неожиданных значений. Так быть не должно, но таковы реалии программирования на языке командной оболочки.