MySQL / 10. Импорт и экспорт данных

Проверка корректности. Сравнение с образцом

Задача
Вам нужно сравнить значение с набором значений, который сложно задать буквально, не используя по-настоящему ужасающее выражение.

Решение
Используйте сравнение с образцом.

Обсуждение
Сравнение с образцом – мощное средство проверки корректности данных: оно позволяет тестировать целые группы значений при помощи одногоединственного выражения. Кроме того, можно использовать сравнение с образцом для разбиения подходящих значений на части для последующих индивидуальных проверок, а также в операциях замены для перезаписи соответствующих значений. Например, можно разбить дату на части, чтобы проверить, находится ли месяц в диапазоне от 1 до 12, а день – в рамках месяца. Или можно использовать замену для преобразования значений MM-DD-YY и DD-MM-YY в формат YY-MM-DD.

Следующие несколько разделов описывают применение шаблонов для проверки различных типов значений, пока же давайте поговорим об общих принципах работы с образцами. Будем рассматривать возможности регулярных выражений Perl, сравнение с образцом в PHP и Python выполняется аналогично (различия описаны в специальной документации). Что касается Java, библиотека класса ORO предоставляет возможности сравнения с образцом, подобные поддерживаемым в Perl; в приложении A указано, как можно получить доступ к этой библиотеке.В Perl конструктором образца является /образец/:

$it_matched = ($val =~ /образец/); # соответствие образцу

Чтобы сделать сравнение с образцом нечувствительным к регистру, добавьте i после конструктора /образец/:

$it_matched = ($val =~ /образец/i); # соответствие образцу, нечувствительное к
регистру

Чтобы использовать символ, отличный от слэша, начните конструктор с m (применяется, если сам образец содержит слэши):

$it_matched = ($val =~ m|образец|); # другой символ конструктора

Чтобы выполнить проверку на несоответствие, замените оператор =~ оператором !~:

$no_match = ($val !~ /образец/); # несоответствие образцу

Чтобы выполнить в $val замену по результатам сравнения с образцом, используйте s/образец/замена/. Если образец встречается в $val, производится замена на замена. Чтобы выполнить сравнение с образцом, нечувствительное к регистру, добавьте i после последнего слэша. Чтобы выполнить глобальную замену – заменить все вхождения образец, а не только первое, добавьте g после последнего слэша:

$val =~ s/образец/замена/; # замена
$val =~ s/образец/замена/i; # замена, нечувствительная к регистру
$val =~ s/образец/замена/g; # глобальная замена
$val =~ s/образец/замена/ig; # глобальная замена, нечувствительная к регистру

Чтобы выполнить сравнение со специальным символом образца, таким как *, ^ или $, предварите его символом обратного слэша. Аналогично, чтобы включить в класс символов символ, имеющий специальное значение в конструкторе класса ([, ] или -), поставьте перед ним символ обратного слэша. Чтобы включить в класс символов литерал ^, укажите его не первым в скобках.

Многие из образцов, используемых в последующих разделах, имеют форму /^образец$/. Такое начало и окончание шаблона приводят к тому, что образец сравнивается со всей исследуемой строкой целиком. Такие проверки наиболее часто встречаются в контексте проверки корректности данных, так как обычно необходима информация о том, совпадает ли образец со всем значением ввода, а не его частью. (Если вы хотите, например, убедиться в том, что значение является целым числом, вам вряд ли пригодятся сведения о том, что оно включает в себя целое число.) Однако это не непреложное правило, и иногда стоит использовать более мягкий тест, опустив символы ^ и $. Например, если вы хотите пропустить начальный и конечный пробелы в значениях, используйте образец, закрепленный только в начале строки, и второй образец, в котором закреплен только конец:

$val =~ s/^\s+//; # отрезаем начальный пробел
$val =~ s/\s+$//; # отрезаем конечный пробел

На самом деле эта операция используется так часто, что является хорошим кандидатом на помещение в библиотечную функцию. Файл Cookbook_Utils.pm содержит функцию trim_whitespace(), которая выполняет обе замены и возвращает результат:

$val = trim_whitespace ($val);

Чтобы запомнить подразделы строки, совпадающей с образцом, используйте скобки для соответствующих частей образца. В случае совпадения вы сможете ссылаться на подстроки при помощи переменных $1, $2 и т. д.:

if ("abcdef" =~ /^(ab)(.*)$/)
{
$first_part = $1; # это будет ab
$the_rest = $2; # это будет cdef
}

Чтобы показать, что элемент образца является необязательным, поставьте после него символ ?. Для сравнения значений с последовательностью цифр, возможно, со знаком «минус», которая может заканчиваться точкой, используйте такой образец:

/^-?\d+\.?$/

Скобки можно использовать и для группировки дизъюнкций внутри образца. Следующий образец соответствует значениям времени в формате hh:mm, за которыми могут (необязательно) следовать AM или PM:

/^\d{1,2}:\d{2}\s*(AM|PM)?$/i

Скобки в этом образце имеют и побочный эффект – необязательная часть запоминается в $1. Чтобы такого не было, используйте (?:образец ):

/^\d{1,2}:\d{2}\s*(?:AM|PM)?$/i

Теперь у вас достаточно базовых знаний о сравнениях с образцами в Perl для создания тестов на корректность различных типов данных. В следующих разделах предлагаются образцы, которые можно использовать для широкой классификации значений, сравнения чисел, временных типов, адресов электронной почты и URL.

Каталог transfer дистрибутива recipes содержит сценарий test_pat.pl, который читает значения ввода, сравнивает их с различными образцами и сообщает о том, каким образцам соответствует каждое из значений. Сценарий поддается наращиванию, так что вы можете использовать его как средство тестирования для собственных образцов.

Статьи по MySQL на эту тему:

Диагностическая утилита для LOAD DATA
Импорт XML в MySQL
Использование временных таблиц для преобразования дат
Использование дат с недостающими частями
Обмен данными между MySQL и FileMaker Pro

Вернуться в раздел: MySQL / 10. Импорт и экспорт данных