5

I'm pretty green at regex with Objective-C. I'm having some difficulty with it.

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\b([1-9]+)\\b" options:NSRegularExpressionCaseInsensitive error:&regError];
if (regError) {
    NSLog(@"%@",regError.localizedDescription);
}
__block NSString *foundModel = nil;
[regex enumerateMatchesInString:self.model options:kNilOptions range:NSMakeRange(0, [self.model length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
    foundModel = [self.model substringWithRange:[match rangeAtIndex:0]];
    *stop = YES;
}];

All I'm looking to do is take a string like

150A

And get

150
rnystrom
  • 1,906
  • 2
  • 21
  • 47

2 Answers2

8

First the problems with the regex:

  1. You are using word boundaries (\b) which means you are only looking for a number that is by itself (e.g. 15 but not 150A).
  2. Your number range does not include 0 so it would not capture 150. It needs to be [0-9]+ and better yet use \d+.

So to fix this, if you want to capture any number all you need is \d+. If you want to capture anything that starts with a number then only put the word boundary at the beginning \b\d+.

Now to get the first occurrence you can use
-[regex rangeOfFirstMatchInString:options:range:]

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\b\\d+" options:NSRegularExpressionCaseInsensitive error:&regError];
if (regError) {
    NSLog(@"%@",regError.localizedDescription);
}

NSString *model = @"150A";
NSString *foundModel = nil;
NSRange range = [regex rangeOfFirstMatchInString:model options:kNilOptions range:NSMakeRange(0, [model length])];
if(range.location != NSNotFound)
{
    foundModel = [model substringWithRange:range];
}

NSLog(@"Model: %@", foundModel);
Joe
  • 56,979
  • 9
  • 128
  • 135
0

What about .*?(\d+).*? ?

Demo: That would backreference the number and you would be able to use it wherever you want.

Javier Diaz
  • 1,791
  • 1
  • 17
  • 25
  • Sorry, this doesn't work as `*` does a *longest* match, so with the input `150A` the first `.*` matches `15`, the `(\d+)` matches `0`, and the final `.*` matches `A`. – CRD Oct 26 '12 at 19:44
  • Sorry, I forget the "lazy" sign – Javier Diaz Oct 26 '12 at 19:45
  • Yes, *shortest* match will do it, but you only need the first one surely? (And of course there are other re's that will do it as well, however a pattern such as @Joe's matches only the required number which is good.) – CRD Oct 26 '12 at 19:54