173

Initial Googling indicates that there's no built-in way to do regular expressions in an Objective-C Cocoa application.

So four questions:

  1. Is that really true?

  2. Are you kidding me?

  3. Ok, then is there a nice open-source library you recommend?

  4. What are ways to get close enough without importing a library, perhaps with the NSScanner class?

dreeves
  • 26,430
  • 45
  • 154
  • 229

10 Answers10

141

I noticed that as of iOS 4.0 Apple provides a NSRegularExpression class. Additionally, as of 10.7, the class is available under OS X.

Mr. DOS
  • 379
  • 2
  • 13
Philip Jespersen
  • 2,816
  • 2
  • 19
  • 9
42
  1. Yes, there's no regex support in Cocoa. If you're only interested in boolean matching, you can use NSPredicate which supports ICU regex syntax. But usually you're interested in the position of the match or position of subexpressions, and you cannot get it with NSPredicate.
  2. As mentioned you can use regex POSIX functions. But they are considered slow, and the regex syntax is limited compared to other solutions (ICU/pcre).
  3. There are many OSS libraries, CocoaDev has an extensive list.
  4. RegExKitLite for example doesn't requires any libraries, just add the .m and .h to your project.

    (My complaint against RegExKitLite is that it extends NSString via category, but it can be considered as a feature too. Also it uses the nonpublic ICU libraries shipped with the OS, which isn't recommended by Apple.)

GenericJon
  • 8,746
  • 4
  • 39
  • 50
mfazekas
  • 5,589
  • 1
  • 34
  • 25
  • 3
    Keep in mind that POSIX regex functions don't work with unicode (ASCII only). – Tom Dalling Aug 02 '09 at 23:53
  • FYI that NSPredicate url is a broken link – taber Oct 12 '10 at 20:23
  • 11
    iOS supports regular expressions for substring searches, e.g. `[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]` – Nestor Apr 28 '11 at 15:23
  • 1
    Also available in Lion (10.7) #if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_3_2 <= __IPHONE_OS_VERSION_MAX_ALLOWED – Maciej Swic Jul 25 '11 at 20:33
  • I find it fine to use nonpublic ICU libraries, because if you need to use it, it's because there's no built-in regex support in your version of Cocoa. If you use those libraries, it also means that you're building for older systems, which will no longer be changed as they're unsupported. If you're building for both old and new, you use the RegExKitLite as fallback if the NSRegularExpression does not exist. (Yes, there are still people working on older systems). –  Dec 08 '13 at 02:45
19

RegexKit is the best I've found yet. Very Cocoa:y. I'm using the "Lite" version in several of our iPhone apps:

sourceforge

lingonikorg

NANNAV
  • 4,875
  • 4
  • 32
  • 50
avocade
  • 1,313
  • 1
  • 14
  • 19
12

You can use the POSIX Regular Expressions library (Yay for a POSIX compliant OS). Try

man 3 regex
Adam Wright
  • 48,938
  • 12
  • 131
  • 152
  • oh, I see. this is a way to do it in straight C, which should presumably work in any objective-C app. cool, thanks! is that basically the accepted way to do this? – dreeves Jan 07 '09 at 21:29
  • It's a way, that doesn't require any additional dependencies. There are other choices, in terms of open source libraries that you could import (PCRE, for Perl regexes, The Boost RegEx library if you're using Obj-C++, or others listed in other answers). – Adam Wright Jan 07 '09 at 21:32
  • Any disadvantages to mixing straight C with Objective-C? Could you maybe include a code snippet for converting to and from NSString? thanks again! – dreeves Jan 07 '09 at 21:45
  • Objective-C is built on top of C, so you're not really mixing anything. Most people use a library though, since it offers an API that's easier to use. – Marc Charbonneau Jan 07 '09 at 23:29
  • 5
    And because POSIX regex functions only work with ASCII strings. – Tom Dalling Aug 02 '09 at 23:58
8

The cheap and dirty hack solution that I use to solve REGEX and JSON parsing issues is to create a UIWebView object and inject Javascript function(s) to do the parsing. The javascript function then returns a string of the value (or list of values) I care about. In fact, you can store a small library set of functions customized for particular tasks and then just call them as needed.

I don't know if it this technique scales to huge volumes of repeated parsing requests, but for quick transactional stuff it gets the job done without depending on any extra external resources or code you might not understand.

Mark Caufman
  • 159
  • 1
  • 3
7

I like the AGRegex framework which uses PCRE, handy if you are used to the PCRE syntax. The best version of this framework is the one in the Colloquy IRC client as it has been upgraded to use PCRE 6.7:

http://colloquy.info/project/browser/trunk/Frameworks/AGRegex

It's very lightweight, much more so than RegExKit (although not as capable of course).

Rob Keniger
  • 45,830
  • 6
  • 101
  • 134
6

NSRegularExpression is available since Mac OS X v10.7 and IOS 4.0.

elp
  • 8,021
  • 7
  • 61
  • 120
bbaassssiiee
  • 6,013
  • 2
  • 42
  • 55
5

During my search on this topic I came across CocoaOniguruma which uses Oniguruma, the Regular Expression engine behind Ruby1.9 and PHP5. It seems a bit newer compared to the existing OregKit (in Japanese). Not sure how these stack up against other bindings.

newtonapple
  • 4,123
  • 3
  • 33
  • 31
4

Googling alittle, found this library: RegexOnNSString

Open source library, containing functions like:

-(NSString *) stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL)ignoreCase

and using NSRegularExpression class. Quite easy to use and no need to worry about anything.

Please, note that NSRegularExpression is available since Mac OS X v10.7 and IOS 4.0, as Datasmid mentioned.

rptwsthi
  • 10,094
  • 10
  • 68
  • 109
nickeyzzz
  • 355
  • 4
  • 13
1

I make it easy. I add a new C++ file to my Objective C project, rename it as .mm, and then create a standard C++ class inside. Then, I make a static class method in the "public:" section for a C++ function that takes an NSString and returns an NSString (or NSArray, if that's what you want). I then convert NSString to C++ std::string like so:

// If anyone knows a more efficient way, let me know in the comments.
// The "if" condition below is because ObjC crashes if converting to
// std::string if the string is nil or empty.
// assume #include <string>
std::string s = "";
if (([sInput != nil]) && (!([sInput isEqualTo:@""]))) {
  std::string sTemp([sInput UTF8String]);
  s = sTemp;
}

From there, I can use regex_replace like so:

// assume #include <regex>
std::string sResult = std::regex_replace(sSource,sRegExp,sReplaceWith);

Then, I can convert that std::string back into an NSString with:

NSString *sResponse2 = @(sResult.c_str());

If you're only using this C++ just for this function, then you may find it suitable to call this file extra.mm (class name Extra) and put this static class method in, and then add other static class methods when the situation arrives where it just makes sense to do it in C++ because it's less hassle in some cases. (There are cases where ObjC does something with less lines of code, and some cases where C++ does it with less lines of code.)

P.S. Still yet another way with this is to use a .mm file but make an Objective C wrapper around the use of std::string and std::regex_replace() (or regex_match()).

Volomike
  • 23,743
  • 21
  • 113
  • 209