В первой части статьи разработчики библиотеки MSLibrary for iOS рассказали об особенностях структуры телефонных номеров с точки зрения международных стандартов, опубликованных в документе RFC 3966 , рассмотрели Международную структуру телефонных номеров, корпоративные WEB стандарты набора телефонного номера, их взаимодействие между собой и то, как ведут себя пользователи.
Как уже было сказано, захват и верификация это — разные задачи, но решаются они схожими методами, различающимися в основном применяемыми в них регулярными выражениями. Во второй части статьи речь пойдет собственно о регулярных выражениях.
Верификация телефонных номеров
Возможно несколько подходов к постановке задачи верификации или валидации строки телефонного номера.
1. выбрать один наиболее простой вариант написания валидного номера и сконструировать для него регулярное выражение
2. рассмотреть максимально большое множество валидных написаний телефонных номеров и сконструировать регулярное выражение под них
Оба подхода имеют право на существование, но каждый из них влечет за собой определенные последствия.
В первом случае либо пользователю придется вводить номер в том виде, в каком производится верификация, что часто приводит к ошибкам и, как следствие, к негативному отношению к приложению. Либо от разработчика потребуется создавать шаблон для ввода данных или дополнительный код, приводящий введенные данные к выбранному валидному виду.
Во втором случае можно обойтись без шаблона и дополнительного кода, ограничившись небольшой инструкцией типа «вводите телефонный номер без пробелов».
Рассмотрим оба варианта, но сначала общие соображения.
Валидация строки телефонного номера, чтобы он был адекватно обработан iOS, сводится к нескольким условиям:
1. общая структура номера должна соответствовать документу RFC 3966
2. телефонный номер должен всегда начинаться и заканчиваться с цифры
3. структура global-number-digits должна соответствовать документу RFC 3966 с учетом п.2 ( см. первую часть статьи )
4. количество цифровых знаков в global-number-digits должно находиться в диапазоне 11-13 цифр (это условие следует из Международной структуры телефонных номеров)
5. структура необязательного элемента — добавочного номера [extension] должна отличаться от предложенной в документе RFC 3966
Подставив соответствующие значения в схему, изображенную на рис.1, получим более подробную структуру телефонного номера валидного для iOS:
И только теперь, убедившись, в том, что полученная структура (рис. 2) удовлетворяет поставленной задаче и международным соглашениям, можно приступать к конструированию регулярных выражений.
Для наглядности начнем с регулярных выражений для каждой из частей структуры, изображенной на рис. 2.
DIGIT
phonedigit
Приступим к конструированию регулярного выражения для первого варианта. Выберем одно, самое простое, написание валидного для iOS систем телефонного номера, например
Регулярное выражение, описывающее структуру этого телефонного номера, выглядит следующим образом:
Разберем это выражение:
Итак, для первого, из рассматриваемых вариантов, следующее регулярное выражение можно использовать для валидации телефонного номера перед его использованием в коде iOS приложения:
Для второго варианта, валидного для iOS систем, телефонного номера, полностью удовлетворяющего структуре, изображенной на рис. 2, регулярное выражение, выглядит следующим образом:
Разберем это выражение:
Итак, для второго, из рассматриваемых вариантов следующее регулярное выражение можно использовать для валидации телефонного номера перед его использованием в коде iOS приложения:
Захват телефонных номеров
Захват — это определение того, что трестируемый набор цифр и знаков может быть телефонным номером. При конструировании регулярного выражения для захвата телефонного номера следует учитывать, что в анализируемой строке:
1. должны содержаться все элементы, необходимые для успешной верификации телефонного номера в необходимой последовательности
2. могут содержаться инородные элементы
3. валидные сепараторы могут быть подменены на невалидными
На втором и третьем пунктах следует остановиться подробнее. Попробуем разобраться в весьма расплывчатых понятиях «инородные» и «невалидные» элементы.
В качестве визуальных сепараторов, кроме рассмотренных выше, при ручном наборе часто используют пробел (whitespace). Пробел может быть использован и как невалидный сепаратор и как инородный элемент, в случае, если он стоит перед или после сепаратора.
Для, обозначения начала добавочного номера, могут быть использованы следующие невалидные сепараторы:
С учетом вышесказанного, регулярное выражение для phonedigit и сепаратора, обозначающего начало добавочного номера, примут следующий вид:
phonedigit
сепаратор добавочного номера
Регулярное выражение, удовлетворяющее поставленным условиям, выглядит следующим образом:
Разберем это выражение:
Итак, для захвата телефонного номера, удовлетворяющего поставленным условиям, можно использовать следующее регулярное выражение:
Для того, чтобы использовать захваченный таким образом телефонный номер, необходимо произвести его нормирование, то есть привести строку к валидному для использования в iOS виду. Описание технологии нормирования выходит за рамки тематики данной статьи. Можно сказать только, что в библиотеке MSLibrary for iOS эта задача решается применением одной единственной функции.
Подведем итоги
Задача верификации или валидации строки телефонного номера решается с помощью одного из следующих регулярный выражений:
Задача захвата строки, содержащей телефонный номер, может быть решена с помощью следующего регулярного выражения:
Использовать полученные регулярные выражения при разработке iOS приложений можно с помощью методов класса NSRegularExpression .
В библиотеке MSLibrary for iOS для этого также имеются свои инструменты. К примеру, функция msfFRMreqMatchesInString
Эта функция принимает значение YES или NO, зависимости от того, удовлетворяет ли строка «string» регулярному выражению «regularExpression» определенное количество раз — «reqNumberOfMatches». Как видите вопрос решается всего в одну строку кода.
Кроме того в библиотеке имеется несколько десятков тщательно подобранных регулярных выражений «на всякие случаи жизни».
Надеемся, что материал был для вас полезен, команда MSLibrary for iOS
Захват и верификация телефонных номеров с помощью регулярных выражений, для iOS и не только… Часть 1
Как уже было сказано, захват и верификация это — разные задачи, но решаются они схожими методами, различающимися в основном применяемыми в них регулярными выражениями. Во второй части статьи речь пойдет собственно о регулярных выражениях.
Верификация телефонных номеров
Возможно несколько подходов к постановке задачи верификации или валидации строки телефонного номера.
1. выбрать один наиболее простой вариант написания валидного номера и сконструировать для него регулярное выражение
2. рассмотреть максимально большое множество валидных написаний телефонных номеров и сконструировать регулярное выражение под них
Оба подхода имеют право на существование, но каждый из них влечет за собой определенные последствия.
В первом случае либо пользователю придется вводить номер в том виде, в каком производится верификация, что часто приводит к ошибкам и, как следствие, к негативному отношению к приложению. Либо от разработчика потребуется создавать шаблон для ввода данных или дополнительный код, приводящий введенные данные к выбранному валидному виду.
Во втором случае можно обойтись без шаблона и дополнительного кода, ограничившись небольшой инструкцией типа «вводите телефонный номер без пробелов».
Рассмотрим оба варианта, но сначала общие соображения.
Валидация строки телефонного номера, чтобы он был адекватно обработан iOS, сводится к нескольким условиям:
1. общая структура номера должна соответствовать документу RFC 3966
telephone-uri = global-number-digits [extension]
рис. 1 2. телефонный номер должен всегда начинаться и заканчиваться с цифры
3. структура global-number-digits должна соответствовать документу RFC 3966 с учетом п.2 ( см. первую часть статьи )
global-number-digits = "+" * DIGIT *phonedigit DIGIT
4. количество цифровых знаков в global-number-digits должно находиться в диапазоне 11-13 цифр (это условие следует из Международной структуры телефонных номеров)
5. структура необязательного элемента — добавочного номера [extension] должна отличаться от предложенной в документе RFC 3966
extension = (";" | *",") 1*(DIGIT *phonedigit DIGIT)
Подставив соответствующие значения в схему, изображенную на рис.1, получим более подробную структуру телефонного номера валидного для iOS:
telephone-uri = "+" DIGIT (9-11)*phonedigit DIGIT [(";" | *",") DIGIT *phonedigit DIGIT]
рис. 2И только теперь, убедившись, в том, что полученная структура (рис. 2) удовлетворяет поставленной задаче и международным соглашениям, можно приступать к конструированию регулярных выражений.
Для наглядности начнем с регулярных выражений для каждой из частей структуры, изображенной на рис. 2.
DIGIT
REGEX [0-9] REGEX_OBJC_STRING @"\\d"
phonedigit
REGEX [0-9]|[-\.\(\)] REGEX_OBJC_STRING @"\\d|[-\\.\\(\\)]"
Приступим к конструированию регулярного выражения для первого варианта. Выберем одно, самое простое, написание валидного для iOS систем телефонного номера, например
+14089961010;1234
Регулярное выражение, описывающее структуру этого телефонного номера, выглядит следующим образом:
REGEX ^((?:\+?[0-9]{11,13})(?:(;|,+)[0-9]+)?)$
Разберем это выражение:
^( # начало строки (?: # начало блока global-number-digits \+? # знак "+" (возможно использование не более одного раза) [0-9] # сегмент DIGIT блока global-number-digits {11,13} # указатель на то, что сегмент DIGIT возможен от 11 до 13 раз ) # окончание блока global-number-digits (?: # начало блока extension (;|,+) # сепаратор, указывающие на начало добавочного номера [0-9]+ # сегмент DIGIT блока extension )? # окончание блока extension )$ # окончание строки
Итак, для первого, из рассматриваемых вариантов, следующее регулярное выражение можно использовать для валидации телефонного номера перед его использованием в коде iOS приложения:
REGEX_OBJC_STRING @"^((?:\\+?\\d{11,13})(?:(;|,+)\\d+)?)$"
Для второго варианта, валидного для iOS систем, телефонного номера, полностью удовлетворяющего структуре, изображенной на рис. 2, регулярное выражение, выглядит следующим образом:
REGEX ^((?:\+?[0-9]([-.\(\)]?[0-9]){10,12})(?:(;|,+)([0-9]([-.\(\)]?[0-9])?)+)?)$
Разберем это выражение:
^( # начало строки (?: # начало блока global-number-digits \+? # знак "+" (возможно использование не более одного раза) [0-9] # первый сегмент DIGIT блока global-number-digits ( # начало сегмента phonedigit блока global-number-digits [-.\(\)]? # визуальный сепаратор (возможно использование не более одного раза в данном сегменте) [0-9] # второй сегмент DIGIT блока global-number-digits ) # окончание сегмента phonedigit блока global-number-digits {10,12} # указатель на то, что сегмент phonedigit возможен от 10 до 12 раз ) # окончание блока global-number-digits (?: # начало блока extension (;|,+) # сепаратор, указывающие на начало добавочного номера ( # начало цифровой части блока extension [0-9] # первый сегмент DIGIT блока extension ( # начало сегмента phonedigit блока extension [-.\(\)]? # визуальный сепаратор (возможно использование не более одного раза в данном сегменте) [0-9] # второй сегмент DIGIT блока extension )? # окончание сегмента phonedigit блока extension )+ # окончание цифровой части блока extension )? # окончание блока extension )$ # окончание строки
Итак, для второго, из рассматриваемых вариантов следующее регулярное выражение можно использовать для валидации телефонного номера перед его использованием в коде iOS приложения:
REGEX_OBJC_STRING @"^((?:\\+?\\d([-.\\(\\)]?\\d){10,12})(?:(;|,+)(\\d([-.\\(\\)]?\\d)?)+)?)$"
Захват телефонных номеров
Захват — это определение того, что трестируемый набор цифр и знаков может быть телефонным номером. При конструировании регулярного выражения для захвата телефонного номера следует учитывать, что в анализируемой строке:
1. должны содержаться все элементы, необходимые для успешной верификации телефонного номера в необходимой последовательности
2. могут содержаться инородные элементы
3. валидные сепараторы могут быть подменены на невалидными
На втором и третьем пунктах следует остановиться подробнее. Попробуем разобраться в весьма расплывчатых понятиях «инородные» и «невалидные» элементы.
В качестве визуальных сепараторов, кроме рассмотренных выше, при ручном наборе часто используют пробел (whitespace). Пробел может быть использован и как невалидный сепаратор и как инородный элемент, в случае, если он стоит перед или после сепаратора.
Для, обозначения начала добавочного номера, могут быть использованы следующие невалидные сепараторы:
"x" | "ext" | ":" | "p" | "="
С учетом вышесказанного, регулярное выражение для phonedigit и сепаратора, обозначающего начало добавочного номера, примут следующий вид:
phonedigit
REGEX [0-9]|(\s?[-\.\(\)\s]\s?) REGEX_OBJC_STRING @"[0-9]|(\\s?[-\\.\\(\\)\\s]\\s?)"
сепаратор добавочного номера
REGEX (x|ext|p|;|=|,+) REGEX_OBJC_STRING @"(x|ext|p|;|=|,+)"
Регулярное выражение, удовлетворяющее поставленным условиям, выглядит следующим образом:
REGEX ^(\s?(?:(\+?\s?[0-9]((\s?[-\.\(\)\s]\s?)?[0-9]){10,12}))(?:((x|ext|p|;|=|,+)(\s?[0-9]((\s?[-\.\(\)\s]\s?)?[0-9])?)+)?)$
Разберем это выражение:
^( # начало строки \s? # пробел, допустимый в начале строки (?:( # начало блока global-number-digits \+? # знак "+" (возможно использование не более одного раза) \s? # пробел, допустимый после знака "+" [0-9] # первый сегмент DIGIT блока global-number-digits ( # начало сегмента phonedigit блока global-number-digits (\s?[-\.\(\)\s]\s?)? # визуальный сепаратор (возможно использование не более одного раза в данном сегменте) [0-9] # второй сегмент DIGIT блока global-number-digits ) # окончание сегмента phonedigit блока global-number-digits {10,12} # указатель на то, что сегмент phonedigit возможен от 10 до 12 раз )) # окончание блока global-number-digits (?:( # начало блока extension (x|ext|p|;|=|,+) # сепаратор, указывающие на начало добавочного номера ( # начало цифровой части блока extension \s? # пробел, допустимый в начале цифровой части блока extension [0-9] # первый сегмент DIGIT блока extension ( # начало сегмента phonedigit блока extension (\s?[-\.\(\)\s]\s?)? # визуальный сепаратор (возможно использование не более одного раза в данном сегменте) [0-9] # второй сегмент DIGIT блока extension )? # окончание сегмента phonedigit блока extension )+ # окончание цифровой части блока extension )? # окончание блока extension )$ # окончание строки
Итак, для захвата телефонного номера, удовлетворяющего поставленным условиям, можно использовать следующее регулярное выражение:
REGEX_OBJC_STRING @"^(\\s?(?:(\\+?\\s?\\d((\\s?[-\\.\\(\\)\s]\\s?)?\\d){10,12}))(?:((x|ext|p|;|=|,+)(\\s?\\d((\\s?[-\\.\\(\\)\\s]\\s?)?\\d)?)+)?)$"
Для того, чтобы использовать захваченный таким образом телефонный номер, необходимо произвести его нормирование, то есть привести строку к валидному для использования в iOS виду. Описание технологии нормирования выходит за рамки тематики данной статьи. Можно сказать только, что в библиотеке MSLibrary for iOS эта задача решается применением одной единственной функции.
Подведем итоги
Задача верификации или валидации строки телефонного номера решается с помощью одного из следующих регулярный выражений:
REGEX_OBJC_STRING @"^((?:\\+?\\d{11,13})(?:(;|,+)\\d+)?)$"
REGEX_OBJC_STRING @"^((?:\\+?\\d([-.\\(\\)]?\\d){10,12})(?:(;|,+)(\\d([-.\\(\\)]?\\d)?)+)?)$"
Задача захвата строки, содержащей телефонный номер, может быть решена с помощью следующего регулярного выражения:
REGEX_OBJC_STRING @"^(\\s?(?:(\\+?\\s?\\d((\\s?[-\\.\\(\\)\s]\\s?)?\\d){10,12}))(?:((x|ext|p|;|=|,+)(\\s?\\d((\\s?[-\\.\\(\\)\\s]\\s?)?\\d)?)+)?)$"
Использовать полученные регулярные выражения при разработке iOS приложений можно с помощью методов класса NSRegularExpression .
В библиотеке MSLibrary for iOS для этого также имеются свои инструменты. К примеру, функция msfFRMreqMatchesInString
BOOL msfFRMreqMatchesInString(NSString *string, NSString *regularExpression, NSInteger reqNumberOfMatches)
рис. 3Эта функция принимает значение YES или NO, зависимости от того, удовлетворяет ли строка «string» регулярному выражению «regularExpression» определенное количество раз — «reqNumberOfMatches». Как видите вопрос решается всего в одну строку кода.
Кроме того в библиотеке имеется несколько десятков тщательно подобранных регулярных выражений «на всякие случаи жизни».
Надеемся, что материал был для вас полезен, команда MSLibrary for iOS
Захват и верификация телефонных номеров с помощью регулярных выражений, для iOS и не только… Часть 1