CocoaPods trunk is moving to be read-only. Read more on the blog, there are 17 months to go.
TestsTested | ✓ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Mar 2016 |
Maintained by Michaël Fortin.
Your regex helper. Makes working with regular expressions in Objective-C short, sweet and performant.
You can perform simple match checks super quickly using Regexer:
BOOL match = [@"Hello World!" rx_matchesPattern:@"[a-zA-Z ]+?!"];
If you would rather extract strings than perform a boolean check for matches, you can do that too. When searching for matches using Regexer, you will obtain zero or more RXMatch
instances. Each RXMatch
represents a single occurrence of the given pattern. An RXMatch
exposes its text, range and an array of RXCapture
s (which are also accessible through indexed subscripting, i.e. square brackets syntax). The first capture in the array is the whole matched pattern ($0) and the following captures correspond to the pattern's capturing groups ($1, $2, ...). Each capture exposes the captured text and its range in the original string.
If you simply want to know whether a given string matches a pattern, you can do it like so:
BOOL match = [@"Hello World!" rx_matchesPattern:@"[a-zA-Z ]+?!"];
BOOL match = [@"Hello World!" rx_matchesPattern:@"[a-z ]+?!" options:NSRegularExpressionCaseInsensitive];
You can quickly obtain the strings and ranges of text matched by your pattern:
NSString *someText = @"What is your quest?";
NSString *pattern = @"\\b[a-zA-Z]+?\\b";
NSArray *texts = [someText rx_textsForMatchesWithPattern:pattern];
NSArray *ranges = [someText rx_rangesForMatchesWithPattern:pattern];
If you're interested in both texts and ranges, it is more efficient to benefit from the fact that Regexer also exposes the matched text and range at the RXMatch
level. This is equivalent to accessing the first capture ($0) in the match, which always corresponds to the whole matched pattern. This is a great way to work with matches if you don't use capturing groups:
NSArray *matches = [someText rx_matchesWithPattern:pattern];
for (RXMatch *match in matches)
{
NSLog(@"Text: %@, Range: [location: %d, length: %d]", [match text],
[match range].location,
[match range].length);
}
The following pattern matches words and captures the first letter of each word using a capturing group, in addition to capturing the whole string matched by the pattern ($0). Using indexed subscripting (the square brackets operator), you can quickly extract any required info:
NSArray *matches = [@"To seek the Holy Grail." rx_matchesWithPattern:@"\\b([a-zA-Z])([a-zA-Z]+?)\\b"];
NSString *word1 = [matches[0][0] text]; // @"To" (equivalent to $0 in regex-speak)
NSString *letter1 = [matches[0][1] text]; // @"T" (equivalent to $1 in regex-speak)
NSString *remainder1 = [matches[0][2] text]; // @"o" (equivalent to $2 in regex-speak)
NSRange word1Range = [matches[0][0] range]; // 0..1 (NSRange)
You can also iterate over matches and/or captures as required:
for (RXCapture *capture in [matches[1] captures])
{
NSLog(@"Text: %@, Range: [location: %d, length: %d]", [capture text],
[capture range].location,
[capture range].length);
}
If you are interested in a single capturing group across all matches of your pattern, you can obtain an array of RXCapture
s for that group, then extract any required info:
NSArray *captures = [@"To seek the Holy Grail." rx_capturesForGroup:1 withPattern:@"\\b([a-zA-Z])([a-zA-Z]+?)\\b"];
NSString *firstLetter1 [captures[0] text] // @"T"
NSString *firstLetter2 [captures[1] text] // @"s"
NSString *firstLetter3 [captures[2] text] // @"t"
NSString *firstLetter4 [captures[3] text] // @"H"
NSString *firstLetter5 [captures[4] text] // @"G"
... or if you're only interested in the text of those captures, you can ask for it directly:
NSArray *texts = [@"To seek the Holy Grail." rx_textsForGroup:1 withPattern:@"\\b([a-zA-Z])([a-zA-Z]+?)\\b"];
// texts == @[@"T", @"s", @"t", @"H", @"G"]
... same goes for ranges:
NSArray *ranges = [@"To seek the Holy Grail." rx_rangesForGroup:1 withPattern:@"\\b([a-zA-Z])([a-zA-Z]+?)\\b"];
// ranges == 0..1, 3..6, ... (NSRange's boxed in NSValue instances)
If you prefer being more explicit and avoid indexed subscripting, you can also manipulate RXMatch
and RXCapture
instances directly:
NSArray *matches = [@"To seek the Holy Grail." rx_matchesWithPattern:@"\\b([a-zA-Z])([a-zA-Z]+?)\\b"];
RXMatch *match = [matches firstObject];
RXCapture *capture = [[match captures] objectAtIndex:0]; // Or: match[0]
NSString *text = [capture text];
NSRange range = [capture range];
If you simply want a pre-compiled, cached NSRegularExpression
instance to perform some more advanced regex operations that may not be covered by Regexer's API, you can obtain one like this:
NSRegularExpression *regex = [@"[a-zA-Z0-9]{10}" rx_regex];
NSRegularExpression *regexWithOptions = [@"[a-zA-Z0-9]{10}" rx_regexWithOptions:NSRegularExpressionCaseInsensitive];
Performing regex-based replacement using Regexer is easy:
NSString *altered = [@"What is your quest?" rx_stringByReplacingMatchesOfPattern:@"\\b([a-zA-Z]+?)\\b" withTemplate:@"$1-hello"];
// Result: @"What-hello is-hello your-hello quest-hello?"
Michaël Fortin ([email protected])
Regexer is available under the MIT license. See the LICENSE file for more info.