rustylepord
rustylepord

Reputation: 5801

Regular Expressions with iOS

I am trying to validate a string against the following regular expression:

[(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}]
  1. The validation passes if it done using the numberOfMatches method as follows:

    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@“[(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}]” options:0 error:&error];
    NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, string.length)];
    
    BOOL status numberOfMatches == string.length;
    
  2. If the validation is done using a NSPredicate the validation fails:

    NSPredicate *test = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", [(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}]];
    BOOL status  = [test evaluateWithObject:string];
    

What's the reason for this? I would like to do this using a NSPredicate.

Upvotes: 0

Views: 210

Answers (1)

nhahtdh
nhahtdh

Reputation: 56809

Surrounding your regex with [] is wrong, since all the content inside is interpreted as part of a character class. In your case:

[(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}]

It is a character class containing A-Z, 0-9, a-z, {}()?=.,*.

Since NSRegularExpression is using ICU's regex library, it supports character class union, like in Java.

The correct regex should be:

^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}$

Your first piece of code with NSRegularExpression should be:

NSRegularExpression *regex = [NSRegularExpression
                                 regularExpressionWithPattern:
                                     @"^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}$"
                                 options:0
                                 error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string
                                    options:0
                                    range:NSMakeRange(0, string.length)];

BOOL status = numberOfMatches == 1;

Since the regex only matches when it matches the whole string, you will get at most 1 match.

Your second piece of code with NSPredicate should be:

NSPredicate *test = [NSPredicate predicateWithFormat:
                            @"SELF MATCHES %@",
                            @"'^(?=.*[A-Z])(?=.*[0-9])(?=.*[a-z]).{6,20}$'"];
BOOL status = [test evaluateWithObject:string];

Note that apart from the escaping of \ which you have to do for the String object literal, you need to take care of another level of escaping for the string literal in predicate syntax (see the example). Luckily, we don't have to care about that here, since you don't use \ in your regex.

The regex should not be specified directly in the format string (like in the previous revision), since it will incur another level of escaping for format string syntax.

Upvotes: 1

Related Questions