Named capture groups using NSRegularExpression

Does NSRegularExpression support named capture groups? This is not like documentation , but I wanted to check before I explore alternative solutions.

+8
regex objective-c cocoa nsregularexpression
source share
3 answers

Named grouping is not supported on iOS, all I can do is use Enum :

Enum:

 typedef enum { kDayGroup = 1, kMonthGroup, kYearGroup } RegexDateGroupsSequence; 

Code example:

 NSString *string = @"07-12-2014"; NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\d{2})\\-(\\d{2})\\-(\\d{4}|\\d{2})" options:NSRegularExpressionCaseInsensitive error:&error]; NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])]; for (NSTextCheckingResult *match in matches) { NSString *day = [string substringWithRange:[match rangeAtIndex:kDayGroup]]; NSString *month = [string substringWithRange:[match rangeAtIndex:kMonthGroup]]; NSString *year = [string substringWithRange:[match rangeAtIndex:kYearGroup]]; NSLog(@"Day: %@, Month: %@, Year: %@", day, month, year); } 
+10
source share

IOS 11 introduced support for a capture name using the API -[NSTextCheckingResult rangeWithName:] .

To get a dictionary of named captures with associated values, you can use this extension (written in Swift, but called from Objective-C):

 @objc extension NSString { public func dictionaryByMatching(regex regexString: String) -> [String: String]? { let string = self as String guard let nameRegex = try? NSRegularExpression(pattern: "\\(\\?\\<(\\w+)\\>", options: []) else {return nil} let nameMatches = nameRegex.matches(in: regexString, options: [], range: NSMakeRange(0, regexString.count)) let names = nameMatches.map { (textCheckingResult) -> String in return (regexString as NSString).substring(with: textCheckingResult.range(at: 1)) } guard let regex = try? NSRegularExpression(pattern: regexString, options: []) else {return nil} let result = regex.firstMatch(in: string, options: [], range: NSMakeRange(0, string.count)) var dict = [String: String]() for name in names { if let range = result?.range(withName: name), range.location != NSNotFound { dict[name] = self.substring(with: range) } } return dict.count > 0 ? dict : nil } } 

A call from Objective-C:

 (lldb) po [@"San Francisco, CA" dictionaryByMatchingRegex:@"^(?<city>.+), (?<state>[AZ]{2})$"]; { city = "San Francisco"; state = CA; } 

Code designation. First, the function should find a list of named captures. Unfortunately, Apple has not published an API for this ( rdar: // 36612942 ).

+3
source share

Since iOS 11 with capturing group names is supported. See my answer here https://stackoverflow.com/a/2208778

+1
source share

All Articles