Хотите потребовать, чтобы ввод содержал только буквы верхнего регистра, пробелы, запятые и точки? Просто измените шаблон подстановки в строке , как показано ниже:
sed 's/[^[: upper: ],]//g'
Эту же функцию можно использовать для простейшей проверки телефонных номеров (допускается присутствие цифр, пробелов, круглых скобок и дефисов, но не допускается наличие пробелов в начале или нескольких пробелов, идущих подряд), если использовать шаблон:
sed 's/[^- [: digit: ]\(\)]//g'
Но, если нужно ограничить ввод целыми числами, опасайтесь ловушки. Например, на первый взгляд кажется, что следующий шаблон справится с этой задачей:
sed 's/[^[: digit: ]]//g'
Однако он будет пропускать только положительные целые числа. А что, если вам необходимо разрешить ввод отрицательных чисел? Если вы просто добавите знак «минус» в множество допустимых символов, функция признает допустимой строку -3–4, хотя совершенно очевидно, что она не является допустимым целым числом. Обработка отрицательных чисел демонстрируется в сценарии № 5.
№ 3. Нормализация форматов дат
Разработчикам сценариев часто приходится иметь дело с большим количеством разнообразных форматов представления дат, нормализация которых может быть сопряжена с разными сложностями. Самые серьезные проблемы связаны с датами, потому что они записываются самыми разными способами. Даже если потребовать ввести дату в определенном формате, например месяц-день-год, вы почти наверняка получите несовместимый ввод: номер месяца вместо названия, сокращенное название вместо полного или даже полное название со всеми буквами в верхнем регистре. По этой причине функция нормализации дат, даже самая простенькая, послужит очень хорошим строительным блоком для многих сценариев, особенно таких, как сценарий № 7.
Код
Сценарий в листинге 1.5 нормализует строки с датами, используя относительно простой набор критериев: месяц должен задаваться именем или числом в диапазоне от 1 до 12, а год — четырехзначным числом. Нормализованная строка с датой включает название месяца (в виде трехсимвольного сокращения), за которым следуют день месяца и четырехзначный год.
Листинг 1.5. Сценарий normdate
··#!/bin/bash
··# normdate — Нормализует поле месяца в строке с датой в трехсимвольное
··#·· представление, с первой буквой в верхнем регистре.
··#·· Вспомогательная функция для сценария № 7, valid-date.
··#·· В случае успеха возвращает 0.
··monthNumToName()
··{
····# Присвоить переменной 'month’ соответствующее значение.
····case $1 in
······1) month="Jan";; 2) month="Feb";;
······3) month="Mar";; 4) month="Apr";;
······5) month="May";; 6) month="Jun";;
······7) month="Jul";; 8) month="Aug";;
······9) month="Sep";; 10) month="Oct";;
······11) month="Nov";; 12) month="Dec";;
······*) echo "$0: Unknown month value $1" >&2
········exit 1
····esac
····return 0
··}
··
··# НАЧАЛО ОСНОВНОГО СЦЕНАРИЯ — УДАЛИТЕ ИЛИ ЗАКОММЕНТИРУЙТЕ ВСЕ, ЧТО НИЖЕ,
··# ЧТОБЫ ЭТОТ СЦЕНАРИЙ МОЖНО БЫЛО ПОДКЛЮЧАТЬ К ДРУГИМ СЦЕНАРИЯМ.
··# =================
··# Проверка ввода
··if [$# −ne 3]; then
····echo "Usage: $0 month day year" >&2
····echo "Formats are August 3 1962 and 8 3 1962" >&2
····exit 1
··fi
··if [$3 −le 99]; then
····echo "$0: expected 4-digit year value." >&2
····exit 1
··fi
··# Месяц введен как число?
··if [-z $(echo $1|sed 's/[[: digit: ]]//g')]; then
····monthNumToName $1
··else
··# Нормализовать до 3 первых букв, первая в верхнем регистре, остальные в нижнем.
····month="$(echo $1|cut −c1|tr '[: lower: ]' '[: upper: ]')"
····month="$month$(echo $1|cut −c2-3 | tr '[: upper: ]' '[: lower: ]')"
··fi
··echo $month $2 $3
··exit 0
Как это работает
Обратите внимание на третий условный оператор в этом сценарии . Он выбрасывает из поля с месяцем все цифры и затем с помощью оператора −z проверяет, получилась ли в результате пустая строка. Если получилась, это означает, что в поле содержатся только цифры, соответственно, его можно напрямую преобразовать в название месяца вызовом функции monthNumToName, которая дополнительно проверяет номер месяца на попадание в диапазон от 1 до 12. Иначе предполагается, что первое поле во введенной строке содержит название месяца, которое нормализуется сложной последовательностью команд cut и tr с использованием двух подоболочек (то есть последовательности команд заключены в скобки $(и), которые вызывают заключенные в них команды и возвращают их вывод).