- Introduction
- Getting Started
- Quick Examples
- Documentation
- Support
- Licensing
- Testing
- Alternatives
- Who Uses It
This project simplifies regular expressions in Objective-C and Swift.
As of iOS 4 (and OSX 10.7), NSRegularExpression
is built-in to Foundation.framework. The syntax is somewhat cumbersome and it leaves much of the work to you, so this library creates categories and macros to simplify usage of NSRegularExpression
.
Here is an example where four lines of code become one:
// Without this library
NSString* string = @"I have 2 dogs.";
NSRegularExpression *regex = [NSRegularExpression regular ExpressionWithPattern:@"\\d+" options:NSRegularExpressionCaseInsensitive error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
BOOL isMatch = match != nil;
// With this library
BOOL isMatch = [@"I have 2 dogs." isMatch:RX(@"\\d+")];
TIP: Refer to the header (RegExCategories.h) for more details and examples.
## Getting StartedThis library has no dependencies and works for iOS 4+ and OSX 10.7+.
### Installing Via CocoaPodsIf you use Cocoa Pods, then just add the following to your Podfile
. Then run pod install
from the command line.
pod 'RegExCategories', '~> 1.0'
You can also just copy these two files into your project:
You may want to add it to your [AppName]-Prefix.pch so that is is available across your code base.
#ifdef __OBJC__
/* ...other references... */
#import "RegExCategories.h"
#endif
You also need to have ARC enabled on your Xcode project. If you don't then add the -fobjc-arc
flag on RegExCategories.m
under Targets > Build Phases > Compile Sources (more info).
You can use these extensions in Swift. There are additional steps you must take to use Objective-C code from Swift. Once you've installed via Cocoa Pods or via download, do the following:
-
Add a Bridging Header
This file will allow you to use objective-c code from your
.swift
code. Create an objective-c header file named [YourProjectName]-Bridging-Header.h -
Configure The Bridging Header
In the
Build Settings
of your main project, scroll down to the "Swift Compiler - Code Generation" section. In "Objective-C Bridging Header" add your file. Typically your value will be[YourProjectName]/[YourProjectName]-Bridging-Header.h
. Build your project - if you have errors then you've set the wrong path. -
Import RegExCategories
In your bridging header, import the header for this library. For example, if you use Cocoa Pods it may look like this:
#import <RegExCategories/RegExCategories.h>
If you just copied the files in to your project, it may look like this:
#import "RegExCategories.h"
Here are some short examples of how you might use the code. The documentation section below goes into full detail.
//Create an NSRegularExpression
Rx* rx = RX(@"\\d");
Rx* rx = [Rx rx:@"\\d"];
Rx* rx = [Rx rx:@"\\d" ignoreCase:YES];
//Test if a string matches
BOOL isMatch = [@"2345" isMatch:RX(@"^\\d+$")];
//Get first match
NSString* age = [@"My dog is 3." firstMatch:RX(@"\\d+")];
//Get matches as a string array
NSArray* words = [@"Hey pal" matches:RX(@"\\w+")];
// words => @[ @"Hey", @"pal" ]
//Get first match with details
RxMatch* match = [@"12.34, 56.78" firstMatchWithDetails:RX(@"\\d+([.]\\d+)")];
// match.value => @"12.34"
// match.range => NSRangeMake(0, 5);
// match.original => @"12.34, 56.78";
// match.groups => @[ RxMatchGroup, RxMatchGroup ];
//Replace with a template string
NSString* result = [@"My dog is 12." replace:RX(@"\\d+") with:@"old"];
// result => @"My dog is old."
//Replace with a block
NSString* result = [RX(@"\\w+") replace:@"hi bud" withBlock:^(NSString* match){
return [NSString stringWithFormat:@"%i", match.length];
}];
// result => @"2 3"
//Replace with a block that has the match details
NSString* result = [RX(@"\\w+") replace:@"hi bud" withDetailsBlock:^(RxMatch* match){
return [NSString stringWithFormat:@"%i", match.value.length];
}];
// result => @"2 3"
You can also use the extensions in Swift, though macros are not available. Most examples are in Objective-C but here are some Swift examples:
//Create an NSRegularExpression
var rx = NSRegularExpression(pattern:"\\d");
var rx = NSRegularExpression.rx("\\d", ignoreCase:true);
var rx = NSRegularExpression.rx("\\d", options: .CaseInsensitive);
//Test if Matches a String
var isMatch = rx.isMatch("3 dogs");
First off, we create an alias for NSRegularExpression named Rx
. So instead of writing NSRegularExpression
you can now use Rx
. (this can be disabled - read on)
//this
NSRegularExpression* rx = [[NSRegularExpression alloc] initWithPattern:@"\\d"];
//can be written as
Rx* rx = [[Rx alloc] initWithPattern:@"\\d"];
We've also created a macro RX()
for quick regex creation. Just pass a string and an NSRegularExpression
object is created:
//this
NSRegularExpression* rx = [[NSRegularExpression alloc] initWithPattern:@"\\d"];
//can be written as
Rx* rx = RX(@"\\d");
These macros can be disabled by defining DisableRegExCategoriesMacros
before you include the script. For example:
#define DisableRegExCategoriesMacros
#include "RegExCategories.h"
Here are a few convenient ways to create an NSRegularExpression
.
######Class Method - rx
Rx* rx = [Rx rx:@"\\d+"];
######Class Method - ignore case
Rx* rx = [Rx rx:@"\\d+" ignoreCase:YES];
######Class Method - with options
Rx* rx = [Rx rx:@"\\d+" options:NSRegularExpressionCaseInsensitive];
######Init With Pattern
Rx* rx = [[Rx alloc] initWithPattern:@"\d+"];
######String Extension
Rx* rx = [@"\\d+" toRx];
######String Extension - ignore case
Rx* rx = [@"\\d+" toRxIgnoreCase:YES];
######String Extension - with options
Rx* rx = [@"\\d+" toRxWithOptions:NSRegularExpressionCaseInsensitive];
Tests whether a regular expression matches a string.
######From NSRegularExpression
BOOL isMatch = [RX(@"\\d+") isMatch:@"Dog #1"];
// => true
######From NSString
BOOL isMatch = [@"Dog #1" isMatch:RX(@"\\d+")];
// => true
Get the character index of the first match. If no match is found, then -1
.
######From NSRegularExpression
int index = [RX(@"\\d+") indexOf:@"Buy 1 dog or buy 2?"];
// => 4
int index = [RX(@"\\d+") indexOf:@"Buy a dog?"];
// => -1
######From NSString
int index = [@"Buy 1 dog or buy 2?" indexOf:RX(@"\\d+")];
// => 4
int index = [@"Buy a dog?" indexOf:RX(@"\\d+")];
// => -1
Split an NSString using a regex as the delimiter. The result is an NSArray of NSString objects.
######From NSRegularExpression
NSArray* pieces = [RX(@"[ ,]") split:@"A dog,cat"];
// => @[@"A", @"dog", @"cat"]
######From NSString
NSArray* pieces = [@"A dog,cat" split:RX(@"[ ,]")];
// => @[@"A", @"dog", @"cat"]
Empty results are not removed. For example:
NSArray* pieces = [@",a,,b," split:RX(@"[,]")];
// => @[@"", @"a", @"", @"b", @""]
Get the first match as an NSString
. If no match is found, nil is returned.
NSString* match = [@"55 or 99 spiders" firstMatch:RX(@"\\d+")];
// => @"55"
NSString* match = [@"A lot of spiders" firstMatch:RX(@"\\d+")];
// => nil
NSString* match = [RX(@"\\d+") firstMatch:@"55 or 99 spiders"];
// => @"55"
If you want more details about the match (such as the range or captured groups), then use match with details. It returns an RxMatch object if a match is found, otherwise nil.
RxMatch* match = [@"55 or 99 spiders" firstMatchWithDetails:RX(@"\\d+")];
// => { value: @"55", range:NSRangeMake(0, 2), groups:[RxMatchGroup, ...] }
RxMatch* match = [@"A lot of spiders" firstMatchWithDetails:RX(@"\\d+")];
// => nil
RxMatch* match = [RX(@"\\d+") firstMatchWithDetails:@"55 or 99 spiders"];
// => { value: @"55", range:NSRangeMake(0, 2), groups:[RxMatchGroup, ...] }
Matches returns all matches as an NSArray
, each as an NSString
. If no matches are found, the NSArray
is empty.
NSArray* matches = [@"55 or 99 spiders" matches:RX(@"\\d+")];
// => @[ @"55", @"99" ]
NSArray* matches = [RX(@"\\d+") matches:@"55 or 99 spiders"];
// => @[ @"55", @"99" ]
Matches with details returns all matches as an NSArray
, each object is an RxMatch object.
NSArray* matches = [@"55 or 99 spiders" matchesWithDetails:RX(@"\\d+")];
// => @[ RxMatch, RxMatch ]
NSArray* matches = [RX(@"\\d+") matchesWithDetails:@"55 or 99 spiders"];
// => @[ RxMatch, RxMatch ]
Replace allows you to replace matched substrings with a templated string.
NSString* result = [RX(@"ruf+") replace:@"ruf ruff!" with:@"meow"];
// => @"meow meow!"
Replace with block lets you pass an objective-c block that returns the replacement NSString
. The block receives an NSString
which is the matched substring.
NSString* result = [RX(@"[A-Z]+") replace:@"i love COW" withBlock:^(NSString*){ return @"lamp"; }];
// => @"i love lamp"
Similar to replace with block, but this block receives an RxMatch for each match. This gives you details about the match such as captured groups.
NSString* result = [RX(@"\\w+") replace:@"two three" withDetailsBlock:^(RxMatch* match){
return [NSString stringWithFormat:@"%i", match.value.length];
}];
// => @"3 5"
Replace can also be called from an NSString
.
NSString* result = [@"ruf ruff!" replaceRX(@"ruf+") with:@"meow"];
// => @"meow meow!"
NSString* result = [@"i love COW" replace:RX(@"[A-Z]+") withBlock:^(NSString*){ return @"lamp"; }];
// => @"i love lamp"
NSString* result = [@"two three" replace:RX(@"\\w+") withDetailsBlock:^(RxMatch* match){
return [NSString stringWithFormat:@"%i", match.value.length];
}];
// => @"3 5"
RxMatch
and RxMatchGroup
are objects that contain information about a match and its groups.
@interface RxMatch : NSObject
/* The substring that matched the expression. */
@property (retain) NSString* value;
/* The range of the original string that was matched. */
@property (assign) NSRange range;
/* Each object is an RxMatchGroup. */
@property (retain) NSArray* groups;
/* The full original string that was matched against. */
@property (retain) NSString* original;
@end
@interface RxMatchGroup : NSObject
/* The substring matched for the group. */
@property (retain) NSString* value;
/* The range of the captured group, relative to the original string. */
@property (assign) NSRange range;
@end
If you need help, submit an issue or send a pull request. Please include appropriate unit tests in any pull requests.
You can visit my website at joshwright.com or tweet at me @BendyTree.
## LicensingMIT License - do whatever you want, just (1) provide attribution and (2) don't hold me liable.
## TestingThis repository includes unit tests written in the XCTest framework.
## AlternativesThere are a few other options for using regular expressions in objective-c including:
- Raw NSRegularExpression - Built in to Foundation since OSX 10.7 and iOS 4.0.
- RegexKitLite - Bridge between NSString and ICU Regex
- CocoaRegex - Alternative bridge to ICU
Here is a list of projects using Objective-C RegEx Categories. If you're using it, tweet at me (@BendyTree) and I'll add you to the list: