G.Abhisek
G.Abhisek

Reputation: 1094

Unable to create Regex in Objective C

I have a regex to check Max 70 alphanumeric characters and special characters: ' / \\ - ; @ and space for which i am using the following regex pattern -

^[a-zA-Z0-9,.-\s'\\\/@]{0,70}$

Please Note: testing this in https://regex101.com works perfectly fine

And the following code to match it with string -

NSString *String = area@123\\
NSRegularExpression *regex  = [NSRegularExpression regularExpressionWithPattern:@"^[a-zA-Z0-9,.-\s'\\\/@]{0,70}$" options:NSRegularExpressionCaseInsensitive error:&error];

NSAssert(regex, @"Unable to create regular expression");
NSRange textRange   = NSMakeRange(0, string.length);
NSRange matchRange  = [regex rangeOfFirstMatchInString:string options:NSMatchingReportProgress range:textRange];

Initially it was showing escape sequence error for which I changed the pattern to - ^[a-zA-Z0-9,.-\\s'\\\\//@]{0,70}$

And now its resulting in crash with message-

Assertion failure in +[UMValidations validateString:withPattern:]
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to create regular expression

Now what wrong is happening when this pattern works great on the regex tester.

Upvotes: 1

Views: 246

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626709

When you write regex patterns in Objective-C, the backslashes with special chars must be doubled. Besides, you need to also escape the hyphen (or place it at the start/end of the character class).

@"^[a-zA-Z0-9,.\\-\\s'\\\\/@]{0,70}$"
               ^^ ^^  ^^^^

You do not need to escape /. You need to use 4 backslashes to define a literal \ because the regex engine uses a literal backslash (in an Objective-C string literal defined as "\\") to escape special characters and to denote a literal \, the literal backslash in the Objective-C string literal must be doubled (\\ in a literal string pattern (so, defined as "\\\\") will match a literal \ in the input). The main point is that the \ in the string literal can form an escape sequence like "\n" (newline) or "\r" (carriage return), etc. So, there are two layers of escaping: one for the Objective-C engine, and the other - for the regex (ICU in this case) library.

See the Objective-C demo:

NSString *String = @"area@123\\";
NSRegularExpression *regex  = @"(?i)^[a-z0-9,.\\-\\s'\\\\/@]{0,70}$";
NSPredicate * Test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
if ([Test evaluateWithObject:String]) {
    NSLog (@"yes");
} else {
    NSLog (@"no");
}

Upvotes: 2

Related Questions