stiefels.net Just another WordPress weblog

24Jan/0713

Regular Expressions for NSString

Last weekend I was looking for different options to validate NSString objects against some regular expressions.
While there are some 3rd party classes for doing regular expressions in Cocoa and wrappers for Perl/PCRE there is a way to do that without external software. The magic word is called [NSPredicate](http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/Reference/NSPredicate.html).
This approach may perhaps not be obvious because there is (at this time) no direct documentation or hint in the [ADC documentation](http://developer.apple.com).

NSPredicate was introduced in OS X 10.4 and is mainly used in CoreData applications to specify queries and has therefore also some nice functionality to filter arrays.
But there is also a way to use its built-in regular expression mechanism to validate NSStrings.

Let's say you have a string "Hello World!" and you want to check if there are at least two sequent l's in it. The regular expression would be: ".\*l{2,}.\*" (without quotes).
Note, that there is a dot followed by an asterisk (which means "zero or more characters") at the beginning and at the end of the actual expression (l{2,}). This is necessary because (unlike the regular expressions in Perl) the "interpolated length" of the regular expression must be at least the same as the length of the string to test to (I don't know why but that's what I found out during my tests).

In your Cocoa application this test would look like this:

NSString *mystring = @"Hello World!";
NSString *regex = @".*l{2,}.*";

NSPredicate *regextest = [NSPredicate
predicateWithFormat:@"SELF MATCHES %@", regex];

if ([regextest evaluateWithObject:mystring] == YES) {
NSLog(@"Match!");
} else {
NSLog(@"No match!");
}

This is easy, isn't it?
All you have to do is to create a NSPredicate object with the predicate "SELF MATCHES" followed by a regular expression and call its "evaluateWithObject:" method with your string you want to validate. It returns YES if the string matches your regular expression and NO if it does not.

If you don't like this approach or if you don't want your application to require OS X 10.4 you can find some other solutions and documentation regarding regular expressions in Cocoa at [this webpage](http://www.cocoadev.com/index.pl?RegularExpressions).

Comments (13) Trackbacks (0)
  1. Obvious in hindsight– many thanks for the cue.

    For the interested, the Predicate Programming Guide states here:

    file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Conceptual/Predicates/index.html#//apple_ref/doc/uid/TP40001789

    that the regexp format is as declared here:

    http://icu.sourceforge.net/userguide/regexp.html

  2. I am new to cocoa programming, and I have this very useful.

    However when I try to use a NSString from another source, ie a file, it no longer matches.

    NSString *taskOutput;
    taskOutput = [[NSString alloc] initWithData: data encoding:NSUTF8StringEncoding];
    

    I believe this an encoding problem, but am at a loss as to what encoding to use.

  3. @Daniel: Give it a try using the same encoding (which one shouldn’t matter) for both your string AND your regular expression.

  4. It appears that my problem is with multi line matching, rather than text encoding.

  5. The backspace in the metacharacters (like in “\d” for a number) has to be escaped in the @”…” string. Confusing if you aren’t used to that.

  6. I am really glad I bumped into this page while looking to support regex in my app. Now I don’t have to link and manage yet another 3rd party framework.

  7. Hi,

    Thanks for the example, it was very useful, I tried it on the simulator and worked perfectly. However, I’m running into this error when I try it on the phone:

    compiling XXXXXXXXXX.m
    NSPredicate undeclared (first use in this function)
    regextest undeclared (first use in this function)
    warning: control reaches end of non-void function

    Any ideas?

  8. iPhone OS Note: The predicate classes—NSPredicate, NSCompoundPredicate, and NSComparisonPredicate—are present only in the Mac OS X version of Foundation.

    http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/Collections/Articles/sortingFilteringArrays.html

  9. For anybody reading this after iPhone OS 3.0 was released, NSPredicate and NSComparisonPredicate are available on the iPhone.

  10. “there is a dot followed by an asterisk (which means “one or more characters”)”

    Actually, * is “zero or more”, + is “one or more”.

  11. Oh, you’re right. Thanks!

  12. Thanks a lot!
    Anyway, this can still be more compact. I just posted a one-line solution at
    http://podstuff.de/blog/nsstring-regex-matching-quick-n-dirty-90


Leave a comment


No trackbacks yet.