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

стр.

№ 6. Проверка ввода: вещественные числа

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

Код

Листинг 1.12. Сценарий validfloat

>#!/bin/bash

># validfloat — Проверяет допустимость вещественного значения.

>#·· Имейте в виду, что сценарий не распознает научную форму записи (1.304e5).

># Чтобы проверить вещественное значение, его нужно разбить на две части:

>#·· целую и дробную. Первая часть проверяется как обычное целое число,

>#·· а дробная — как положительное целое число. То есть число -30.5 оценивается

>#·· как допустимое, а -30.-8 нет.

># Подключение других сценариев к текущему осуществляется с помощью оператора"."

># Довольно просто.

>. validint

>validfloat()

>{

>··fvalue="$1"

>··# Проверить наличие десятичной точки.

>··if [! -z $(echo $fvalue | sed 's/[^.]//g')]; then

>····# Извлечь целую часть числа, слева от десятичной точки.

>····decimalPart="$(echo $fvalue | cut −d. -f1)"

>····# Извлечь дробную часть числа, справа от десятичной точки.

>····fractionalPart="${fvalue#*\.}"

>····# Проверить целую часть числа, слева от десятичной точки

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

>······# "!" инвертирует логику проверки, то есть ниже проверяется

>······#·· "если НЕ допустимое целое число"

>······if! validint "$decimalPart" "" ""; then

>········return 1

>······fi

>····fi

>····# Теперь проверим дробную часть.

>····# Прежде всего, она не может содержать знак "минус" после десятичной точки,

>····#·· например: 33.-11, поэтому проверим знак '-’ в дробной части.

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

>······echo "Invalid floating-point number: '-' not allowed \

>········after decimal point." >&2

>······return 1

>····fi

>····if ["$fractionalPart"!= ""]; then

>······# Если дробная часть НЕ является допустимым целым числом…

>······if! validint "$fractionalPart" "0" ""; then

>········return 1

>······fi

>····fi

>··else

>····# Если все значение состоит из единственного знака "-",

>····#·· это недопустимое значение.

>····if ["$fvalue" = "-"]; then

>······echo "Invalid floating-point format." >&2

>······return 1

>····fi

>····# В заключение проверить, что оставшиеся цифры представляют

>····# допустимое целое число.

>····if! validint "$fvalue" "" ""; then

>······return 1

>····fi

>··fi

>··return 0

>}

Как это работает

Сценарий сначала проверяет наличие десятичной точки во входном значении

. Если точки в числе нет, это не вещественное число. Далее для анализа извлекаются целая
и дробная
части числа. Затем, в строке
, сценарий проверяет, является ли целая часть (слева от десятичной точки) допустимым целым числом. Следующая последовательность проверок сложнее, потому что требуется проверить
отсутствие дополнительного знака «минус» (чтобы исключить такие странные числа, как 17. –30) и убедиться, что дробная часть (справа от десятичной точки) является допустимым целым числом.

Последняя проверка в строке

выясняет, не является ли проверяемое значение единственным знаком «минус» (такое число выглядело бы слишком странно, чтобы пропустить его).

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

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

Если во время выполнения функции не будет выведено сообщения об ошибке, она вернет 0 для числа, являющегося допустимым вещественным значением. Чтобы протестировать сценарий, добавьте в конец следующие строки кода:

>if validfloat $1; then

>··echo "$1 is a valid floating-point value."

>fi

>exit 0

Если попытка подключить сценарий validint сгенерирует ошибку, убедитесь, что он находится в одном из каталогов, перечисленных в PATH, или просто скопируйте функцию validint непосредственно в начало сценария validfloat.

Результаты

Сценарий validfloat принимает единственный аргумент для проверки. Листинг 1.13 демонстрирует проверку нескольких значений с помощью validfloat.