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

стр.

Листинг 1.13. Тестирование сценария validfloat

>$ validfloat 1234.56

>1234.56 is a valid floating-point value.

>$ validfloat -1234.56

>-1234.56 is a valid floating-point value.

>$ validfloat —.75

>-.75 is a valid floating-point value.

>$ validfloat -11.-12

>Invalid floating-point number: '-' not allowed after decimal point.

>$ validfloat 1.0344e22

>Invalid number format! Only digits, no commas, spaces, etc.

Если вы увидите лишний вывод, это может объясняться присутствием строк, добавленных ранее в validint для тестирования, которые вы забыли удалить перед переходом к этому сценарию. Просто вернитесь назад, к описанию сценария № 5 и закомментируйте или удалите строки, добавленные для тестирования функции.

Усовершенствование сценария

Было бы круто добавить в функцию поддержку научной формы записи, продемонстрированной в последнем примере. Это не так уж трудно. Вам нужно проверить присутствие в числе символа 'e’ или 'E’ и затем разбить его на три сегмента: целую часть (всегда представлена единственной цифрой), дробную часть и степень числа 10. После этого каждую часть можно проверить с помощью validint.

№ 7. Проверка форматов дат

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

Ниже приводится набор критериев, проверка которых позволяет сказать, является ли проверяемый год високосным:

• Если год не кратен 4, он не високосный.

• Если год делится на 4 и на 400 — это високосный год.

• Если год делится на 4 и не делится на 400, но делится на 100 — это не високосный год.

• Все остальные годы, кратные 4, являются високосными.

Просматривая исходный код в листинге 1.14, обратите внимание, что для нормализации исходной даты перед проверкой этот сценарий использует normdate.

Код

Листинг 1.14. Сценарий valid-date

>··#!/bin/bash

>··# valid-date — Проверяет дату с учетом правил определения високосных лет

>··normdate="укажите здесь имя файла, в котором вы сохранили сценарий normdate.sh"

>··exceedsDaysInMonth()

>··{

>····# С учетом названия месяца и числа дней в этом месяце, данная функция

>····# вернет: 0, если указанное число меньше или равно числу дней в месяце;

>····# 1 — в противном случае.

>

····case $(echo $1|tr '[: upper: ]' '[: lower: ]') in

>······jan*) days=31;; feb*) days=28;;

>······mar*) days=31;; apr*) days=30;;

>······may*) days=31;; jun*) days=30;;

>······jul*) days=31;; aug*) days=31;;

>······sep*) days=30;; oct*) days=31;;

>······nov*) days=30;; dec*) days=31;;

>········*) echo "$0: Unknown month name $1" >&2

>············exit 1

>····esac

>····if [$2 −lt 1 −o $2 −gt $days]; then

>······return 1

>····else

>······return 0 # Число месяца допустимо.

>····fi

>··}

>··isLeapYear()

>··{

>····# Эта функция возвращает 0, если указанный год является високосным;

>····#·· иначе возвращается 1.

>····# Правила проверки високосного года:

>····#·· 1. Если год не делится на 4, значит, он не високосный.

>····#·· 2. Если год делится на 4 и на 400, значит, он високосный.

>····#·· 3. Если год делится на 4, не делится на 400 и делится

>····#······на 100, значит, он не високосный.

>····#·· 4. Любой другой год, который делится на 4, является високосным.

>····year=$1

>

····if ["$((year % 4))" −ne 0]; then

>······return 1 # Nope, not a leap year.

>····elif ["$((year % 400))" −eq 0]; then

>······return 0 # Yes, it's a leap year.

>····elif ["$((year % 100))" −eq 0]; then

>······return 1

>····else

>······return 0

>····fi

>··}

>··# Начало основного сценария

>··# =================

>··if [$# −ne 3]; then

>····echo "Usage: $0 month day year" >&2

>····echo "Typical input formats are August 3 1962 and 8 3 1962" >&2

>····exit 1

>··fi

>··# Нормализовать дату и сохранить для проверки на ошибки.

>

··newdate="$($normdate "$@")"

>··if [$? -eq 1]; then

>····exit 1 # Error condition already reported by normdate