How to use regular expression in Cocoa/Objective-C

I have heard that Apple added regular expression search in NSString, but I’m not sure.
Although I searched NSString messages but couldn’t find any. However, in NSPredicate, it supports regular expression. However, NSPredicate is used usually with NSArray on which you want to search certain objects which contains string pattern you want to find.

Then, to find certain patterns in a given string, how will you use a pattern matching functionality provided by the system?
You can use “regex” library of Unix.
Here is a sample.


#import <regex.h>

// searchIPAddressFrom
// search IP address from the passed sourceString
//
// returns a found string in NSString form.
//			nil, if not found
- (NSString *)searchIPAddressFrom:(NSString *)sourceString
{
	int isFail;
	
	char *regexPattern = "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}"; // For IP address
	
	regex_t regex;
	regmatch_t pmatch[5]; // track up to 5 maches. Actually only one is needed.
	
	const char *sourceCString;
	char errorMessage[512], foundCString[16];
	
	NSString *errorMessageString;
	NSString *foundString = nil;
	
	sourceCString = [sourceString UTF8String];
	
	// setup the regular expression
	
	@try{
		
		NSException *exception;
		
		if( isFail = regcomp(&regex, regexPattern, REG_EXTENDED) )
		{
			regerror(isFail, &regex, errorMessage, 512);
			errorMessageString = [NSString stringWithCString:errorMessage];
			
			exception = [NSException exceptionWithName:@"RegexException" 
												reason:errorMessageString 
											  userInfo:nil];
			@throw exception;
		}
		else
		{
			if( isFail = regexec( &regex, sourceCString, 5, pmatch, 0 ) )
			{
				regerror( isFail, &regex, errorMessage, 512 );
				errorMessageString = [NSString stringWithCString:errorMessage];
				exception = [NSException exceptionWithName:@"RegexException"
													reason:errorMessageString
												  userInfo:nil];
				@throw exception;
			}
			else
			{
				snprintf( foundCString, pmatch[0].rm_eo - pmatch[0].rm_so + 1, 
						 "%s", &sourceCString[pmatch[0].rm_so] );
				
				foundString = [NSString stringWithCString:foundCString];
			}
		}
	}
	@catch( NSException *caughtException ) {
		NSLog(@"%@ occurred due to %@", [caughtException name], [caughtException reason]);
	}
	@finally {
		regfree(&regex);		
	}	
	
	return foundString;
}

It is very straight forward. Because the regex library is common to any Unix system, you can use it with your C/C++ codes.

4 responses to this post.

  1. Posted by Stallion on February 8, 2012 at 6:20 PM

    Has apple added regular expressions in the NSString class yet?

    Reply

    • Posted by jongampark on February 8, 2012 at 8:51 PM

      They did for Mac OS X 10.7 also.
      The NSString has this option : NSRegularExpressionSearch
      Also, there is a new class, NSRegularExpression.
      If you search at Apple’s developer site or local document, it will reveal how to use them.

      Reply

  2. Posted by Romain TAILLANDIER on June 10, 2013 at 10:32 PM

    The Regex you are proposing is not very accurate and match 666.666.666.666, witch is not valid.
    “(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)”

    Romain TAILLANDIER

    Reply

    • Posted by jongampark on June 10, 2013 at 10:42 PM

      Yes, there can be some cases I overlooked. However if you took mine as a base and enhance it, it’s good, isn’t it?

      Reply

Leave a comment