Сценарии командной оболочки. 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 — в противном случае.
>
>······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
>
>······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
>··# Нормализовать дату и сохранить для проверки на ошибки.
>
>··if [$? -eq 1]; then
>····exit 1 # Error condition already reported by normdate