📜 ⬆️ ⬇️

NSRegularExpression and NSDataDetector - Quick Start

Working with regular expressions in iOS 10

Hello! In this article we will discuss how to work with NSRegularExpression and NSDataDetector,
all those who are not indifferent are invited under cat.

some_text



A regular expression is a string or sequence of characters that define a pattern. With which you can make very flexible search samples in the text.
')
Suppose we have some text in a line and our task is to find all the listed email addresses in it. The best tool for this task is regular expressions.

Writing R.V. (Regular Expression) for checking email. First you need to describe the basic conditions of all possible combinations of types of email addresses. In the most minimal version, it can be the following: a@b.io


We start to make RVs in stages:

@ " ([a-z0-9]) "
- says that the name of the box can contain any letter and any number



@ "([a-z0-9]) {1.64} "
- says that a group of these characters can be from 1 to 64 characters long



@ "([a-z0-9 ! # $% & '* + - / =? ^ _` {|} ~ ]) {1.64} "
- says that you can also specify these characters



@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @ "
- says that the dog at this place is required



@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @ ([a-z0-9! # $% &' * + - / =? ^ _ `{|} ~]) {1.64}"
- Add all the same characters, only after @



@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @ ([a-z0-9! # $% &' * + - / =? ^ _ `{|} ~]) {1.64} \\. "
- says that the dot character on this place is required



@ "([a-z0-9! # $% & '* + - / =? ^ _` {|} ~]) {1.64} @ ([a-z0-9! # $% &' * + - / =? ^ _ `{|} ~]) {1.64} \\. ([A-z0-9]) {2.64} "
- says that the domain name can contain letters and numbers of the total amount of characters from 2 to 64 characters



some_text

We just made a full-fledged regular expression.

Incomplete reference book of reserved characters for PB:




SymbolValue
^beginning of the line to be checked
$end of line to be checked
.any character
|logical OR
?preceding character or group of characters is optional
+one or more instances of the previous item
*any number of instances of the item (including zero
\ dnumeric character
\ Dnot numbers symbol
\ swhitespace
\ Snot white space
\ wmatches any letter or number; equivalent of [a-zA-Z0-9_]
\ Won the contrary, the equivalent of [^ a-zA-Z0-9_], all characters except these
Quantifiers
{n}exactly n times
{m, n}inclusive M to N
{m,}at least m times
{, n}no more than n times
()group creation
[]in such brackets we say, "any character of these, but only one

Creating NSRegularExpression


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    ,      } 

For the sake of justice, I should note that when creating a pattern, we must write in the string not easy \ w, (or any other letter or symbol that is reserved)
and write backslash twice to escape NSString. \\ w



NSRegularExpression instance manipulation


Total number of all matches found

  NSUInteger numberOfMatches = [regex numberOfMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length])]; 




Returns the range of the first match.

  NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:_mainText options:0 range:NSMakeRange(0, [_mainText length])]; if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) { NSString *substringForFirstMatch = [_mainText substringWithRange:rangeOfFirstMatch]; } 




Get an array of all matches found.

  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]; } 




We get the first match of the total

  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]; } 




We iterate through the block for each match

  __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; }]; 




Finding our pattern in the text and insert the word Sieg in its place !!!

  NSString *modifiedString = [regex stringByReplacingMatchesInString:_mainText options:0 range:NSMakeRange(0, [_mainText length]) withTemplate:@"Sieg!!!"]; 




NSDataDetector class overview


NSDataDetector is a subclass of NSRegularExpression , made for easy searching (links, phone numbers, dates, etc.). That is, this actual class under its hood contains universal regular expressions for finding the above.

Also, the NSDataDetector can call all NSRegularExpression methods, also look for firstMatch / matches for all text, etc.

Manipulating the NSDataDetector instance




Creating an instance of NSDataDectector

  NSError* error1 = nil; NSDataDetector* detector=[NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink | NSTextCheckingTypePhoneNumber error:&error]; /*  ,     NSTextCheckingTypeOrthography NSTextCheckingTypeSpelling NSTextCheckingTypeGrammar NSTextCheckingTypeDate NSTextCheckingTypeAddress NSTextCheckingTypeLink NSTextCheckingTypeQuote NSTextCheckingTypeDash NSTextCheckingTypeReplacement NSTextCheckingTypeCorrection NSTextCheckingTypeRegularExpression NSTextCheckingTypePhoneNumber NSTextCheckingTypeTransitInformation */ 




Number of matches found in the text

 NSUInteger numberOfMatchesFromDetect = [detector numberOfMatchesInString:_mainText options:0 range:NSMakeRange(0,[_mainText length])]; 




All matches in one array (it contains NSTextCheckingResult objects)

  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); } } 




We pass a block on all matches

  __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++; }]; 




Brief documentation of properties
Property instance NSRegularExpressionTreatment
var pattern: StringReturns a regular expression pattern.
var options: NSRegularExpression.OptionsReturns the search parameters for example: look for case insensitive NSRegularExpressionCaseInsensitive.
var numberOfCaptureGroups: intReturns the number of groups from the regular expression pattern, for example: @ »^ (ab | bc) (amg | img) $" - here are two groups

Everyone who read to the end and put a thumbs up, I will be very grateful.
The project can be found at this link: here

Source: https://habr.com/ru/post/322380/


All Articles