Search code examples
objective-cregexxcode4nsregularexpression

capturing a string before and after some data using regular expressions in ObjectiveC


I am relatively new to regex expressions and needed some advice.

The goal is to the get data in the following format into an array:

  • value=777
  • value=888

From this data: "value=!@#777!@#value=@#$888*"

Here is my code (Objective C):

NSString *aTestString = @"value=!@#777!@#value=@#$**888***";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"value=(?=[^\d])(\d)" options:0 error:&anError];

So my questions are:

1) Can the regex engine capture data that is split like that? Retrieving the "value=" removing the garbage data in the middle, and then grouping it with its number "777" etc?

2) If this can be done, then is my regex expression valid? value=(?=[^\d])(\d)


Solution

  • The lookahead (?=) is wrong here, you haven't correctly escaped the \d (it becomes \\d) and last but not least you left out the quantifiers * (0 or more times) and + (1 or more times):

    NSString *aTestString = @"value=!@#777!@#value=@#$**888***";
    NSRegularExpression *regex = [NSRegularExpression
        regularExpressionWithPattern:@"value=[^\\d]*(\\d+)"
        options:0
        error:NULL
    ];
    
    [regex 
        enumerateMatchesInString:aTestString
        options:0
        range:NSMakeRange(0, [aTestString length])
        usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
            NSLog(@"Value: %@", [aTestString substringWithRange:[result rangeAtIndex:1]]);
        }
    ];
    

    Edit: Here's a more refined pattern. It catches a word before =, then discards non-digits and catches digits afterwards.

    NSString *aTestString = @"foo=!@#777!@#bar=@#$**888***";
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\w+)=[^\\d]*(\\d+)" options:0 error:NULL];
    
    [regex 
        enumerateMatchesInString:aTestString
        options:0
        range:NSMakeRange(0, [aTestString length])
        usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
            NSLog(
                @"Found: %@=%@",
                [aTestString substringWithRange:[result rangeAtIndex:1]],
                [aTestString substringWithRange:[result rangeAtIndex:2]]
            );
        }
    ];
    
    // Output:
    // Found: foo=777
    // Found: bar=888