Сценарии командной оболочки. Linux, OS X и Unix. 2-е издание - страница 16

стр.

Код

Листинг 1.9. Сценарий validint

>#!/bin/bash

># validint — Проверяет целые числа, поддерживает отрицательные значения

>validint()

>{

>··# Проверяет первое значение и сравнивает с минимальным значением $2 и/или

>··#·· с максимальным значением $3, если они заданы. Если проверяемое значение

>··#·· вне заданного диапазона или не является допустимым целым числом,

>··#·· возвращается признак ошибки.

>··number="$1"; min="$2"; max="$3"

>··if [-z $number]; then

>····echo "You didn't enter anything. Please enter a number." >&2

>····return 1

>··fi

>··# Первый символ — знак "минус"?

>··if ["${number%${number#?}}" = "-"]; then

>····testvalue="${number#?}" # Оставить для проверки все, кроме первого символа

>··else

>····testvalue="$number"

>··fi

>··# Удалить все цифры из числа для проверки.

>··nodigits="$(echo $testvalue | sed 's/[[: digit: ]]//g')"

>··# Проверить наличие нецифровых символов.

>··if [! -z $nodigits]; then

>····echo "Invalid number format! Only digits, no commas, spaces, etc." >&2

>····return 1

>··fi

>··if [! -z $min]; then

>····# Входное значение меньше минимального?

>····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 и 0 — в случае успеха.

Запуск сценария

Весь сценарий целиком является функцией. Его можно скопировать в другой сценарий или подключить как библиотечный файл. Чтобы преобразовать его в команду, просто добавьте в конец файла код из листинга 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

Но он не работает, потому что, даже если первое выражение, слева от оператора И, вернет ложное значение, нет никаких гарантий, что вторая проверка не будет выполнена (хотя в большинстве других языков программирования получилось бы именно так). То есть вы рискуете столкнуться со множеством ошибок из-за сравнения недействительных или неожиданных значений. Так быть не должно, но таковы реалии программирования на языке командной оболочки.