- PVSM.RU - https://www.pvsm.ru -
Работа с регулярными выражениями в iOS 10
Всем привет! В этой статье мы разберем как работать с NSRegularExpression и NSDataDetector,
всех неравнодушных приглашают под кат.
Допустим у нас имеется некий текст в строке и наша задача найти в нем все перечисленные email-адреса. Самый лучший инструмент для этой задачи это регулярные выражения.
Пишем Р.В. (Регулярное Выражение) для проверки email. Для начала нужно описать базовые условия всех возможных комбинаций видов эл.адресов. В самом минимальном варианте, он может иметь следующий вид: a@b.io
Начинаем составлять РВ поэтапно:
@"([a-z0-9])"
— говорит, что имя ящика может содержать любую букву и любую цифру
Только что мы составили полноценное регулярное выражение.
Символ | Значение |
---|---|
^ | начало проверяемой строки |
$ | конец проверяемой строки |
. | любой символ |
| | логическое ИЛИ |
? | предшествующий символ или группа символов является необязательными |
+ | один или несколько экземпляров предшествующего элемента |
* | любое количество экземпляров элемента (в том числе и нулевое |
d | цифровой символ |
D | не циф. символ |
s | пробельный символ |
S | не пробельный символ |
w | соответствует любой букве или цифре; эквивалент [a-zA-Z0-9_] |
W | наоборот эквивалент [^a-zA-Z0-9_], все символы кроме этих |
Квантификаторы | |
{n} | ровно n раз |
{m,n} | включительно от M до N |
{m,} | не менее m раз |
{,n} | не более n раз |
() | создание группы |
[] | в таких скобках говорим, «любой символ из этих, но только один |
self.mainText = @"There’s also +39(081)-552-1488 a “Bookmark” button that allows the user to highlight any date, time or location in the text. For simplicity’s sake, www.ok.ru you won’t
+39(081)552 2080 not cover every possible format of date, time and 2693485 location strings that can appear in your text. You’ll implement the https://github.com bookmarking functionality +249-54-85 at the very end +39 333 3333333 of the tutorial. vk.com Your first step to getting the search
functionality working is to turn standard strings representing regular expressions into http://app.com NSRegularExpression objects.";
NSString* pattern = @"\b(in)|(or)\b"; // Хотим искать слова "in" или "or"
NSRegularExpressionOptions regexOptions = NSRegularExpressionCaseInsensitive; // Поиск вне зависимости от регистра
NSError* error = NULL;
// Само создание регулярного выражения
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern
options:regexOptions
error:&error];
if (error){
NSLog(@"Ошибка при создании Regular Expression"); // Если в pattern были внесены корректные данные, тогда это сообщение не появиться
}
Справедливости ради должен отметить, что при создании паттерна, в строке мы должны писать непросто w,(или любую другую букву или символ который зарезервирован)
а писать backslash два раза что бы экранировать NSString. \w
Общее количество всех найденных совпадений
NSUInteger numberOfMatches = [regex numberOfMatchesInString:_mainText
options:0
range:NSMakeRange(0, [_mainText length])];
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:_mainText
options:0
range:NSMakeRange(0, [_mainText length])];
if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) {
NSString *substringForFirstMatch = [_mainText substringWithRange:rangeOfFirstMatch];
}
NSArray *matches = [regex matchesInString:_mainText
options:0
range:NSMakeRange(0, [_mainText length])];
for (NSTextCheckingResult *match in matches) {
//=== Через проперти resultType, можно проверить
// к какому типу относиться найденый матч
if (match.resultType == NSTextCheckingTypeQuote) NSLog(@"Цитата!");
NSRange matchRange = [match range];
NSRange firstHalfRange = [match rangeAtIndex:1];
NSRange secondHalfRange = [match rangeAtIndex:2];
}
NSTextCheckingResult *match = [regex firstMatchInString:_mainText
options:0
range:NSMakeRange(0, [_mainText length])];
if (match) {
NSRange matchRange = [match range];
NSRange firstHalfRange = [match rangeAtIndex:1];
NSRange secondHalfRange = [match rangeAtIndex:2];
}
__block NSUInteger count = 0;
[regex enumerateMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){
NSRange matchRange = [match range];
NSRange firstHalfRange = [match rangeAtIndex:1];
NSRange secondHalfRange = [match rangeAtIndex:2];
if (++count >= 100) *stop = YES;
}];
NSString *modifiedString = [regex stringByReplacingMatchesInString:_mainText
options:0
range:NSMakeRange(0, [_mainText length])
withTemplate:@"Sieg!!!"];
NSDataDetector — это подкласс NSRegularExpression, сделанный для удобного поиска (ссылок, номеров телефонов, даты и т.д.). То есть фактический этот класс у себя под капотом содержит универсальные регулярные выражения для поиска вышеперечисленного.
Также NSDataDetector может вызывать все методы NSRegularExpression, также искать firstMatch/matches всего текста и т.д.
NSError* error1 = nil;
NSDataDetector* detector=[NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink |
NSTextCheckingTypePhoneNumber
error:&error];
/* Типы данных, того чего можно искать
NSTextCheckingTypeOrthography
NSTextCheckingTypeSpelling
NSTextCheckingTypeGrammar
NSTextCheckingTypeDate
NSTextCheckingTypeAddress
NSTextCheckingTypeLink
NSTextCheckingTypeQuote
NSTextCheckingTypeDash
NSTextCheckingTypeReplacement
NSTextCheckingTypeCorrection
NSTextCheckingTypeRegularExpression
NSTextCheckingTypePhoneNumber
NSTextCheckingTypeTransitInformation
*/
NSUInteger numberOfMatchesFromDetect = [detector numberOfMatchesInString:_mainText
options:0
range:NSMakeRange(0,[_mainText length])];
NSArray* matchesFromDetect =[detector matchesInString:_mainText
options:0
range:NSMakeRange(0,[_mainText length])];
// ----- Проходим по каждому совпадению и смотрим что там
for (NSTextCheckingResult* match in matchesFromDetect)
{
NSLog(@"------------");
NSRange matchRange = [match range];
if ([match resultType] == NSTextCheckingTypeLink)
{
NSURL* url = [match URL];
NSLog(@"url = %@",url.absoluteString);
} else if ([match resultType] == NSTextCheckingTypePhoneNumber)
{
NSString *phoneNumber = [match phoneNumber];
NSLog(@"phone = %@",phoneNumber);
}
}
__block NSUInteger countForDectect = 0;
[detector enumerateMatchesInString:_mainText
options:0
range:NSMakeRange(0, [_mainText length])
usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
NSRange matchRange = result.range;
NSLog(@"In Enumerate = %d, tRange = %@t tText = %@",countForDectect, NSStringFromRange(matchRange), [_mainText substringWithRange:matchRange]);
countForDectect++;
}];
Проперти экземпляра NSRegularExpression | Трактовка |
---|---|
var pattern: String | Возвращает паттерн регулярного выражения. |
var options: NSRegularExpression.Options | Возвращает параметры поиска например: ищем без учета регистра NSRegularExpressionCaseInsensitive. |
var numberOfCaptureGroups: Int | Возвращает количество групп из паттерна регулярного выражения, например: @»^(ab|bc)(amg|img)$" — тут две группы |
Всем кто дочитал до конца и поставил палец вверх, буду очень признателен.
Проект можно найти по этой ссылке: здесь [1]
Автор: hack_developer
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/ios/245639
Ссылки в тексте:
[1] здесь: https://github.com/HackDeveloperUA/NSRegularExpression_Example/tree/master
[2] Источник: https://habrahabr.ru/post/322380/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.