I'm using RKL in a Cocoa app to parse log statements from a wrapped task.
Pattern:
(?:.+) \[.+?\] (.+) \[.+?\] logged in (?:.+)
Test data:
2011-07-11 00:48:19 [INFO] Preparing spawn area: 97
2011-07-11 00:48:19 [INFO] Done (2175837000ns)! For help, type "help" or "?"
2011-07-11 00:48:42 [INFO] mikeyward [/127.0.0.1:59561] logged in with entity id blahblah
Every RegEx tester开发者_如何学Python I've tried on the internet successfully matches the third line and captures 'mikeyward'.
Objective-C code:
NSString *loggedInPattern = @"(?:.+) \\[.+?\\] (.+) \\[.+?\\] logged in (?:.+)";
NSArray *captures = [searchString arrayOfCaptureComponentsMatchedByRegex:loggedInPattern];
NSString *username = [captures objectAtIndex:0];
Problem: Despite having checked to ensure that searchString is valid and contains the sample data, RKL fails to match the line, let alone capture the username. In the example above, an exception is thrown because the captures array is returned with zero objects and I'm not error-checking :)
Any assistance in understanding why regex checkers confirm the match and capture but RKL misses it would be very much appreciated.
Thanks~
Your matcher is only doing single line matching. Use the version with options and pass it RKLMultiline
Your problem may be related to this one, or it might just be a case of catastrophic backtracking. My advice would be the same in either case: write the regex so none of the quantifiers have overlapping spans of influence. For example:
(?m)^[ 0-9:-]+\[[A-Z]+\] (\S+) \[[^\]]+\] logged in .+$
In your regex, the first (?:.+)
initially gobbles up all the characters in the line, only to have to give most of them back so the rest of the regex can have a chance to match. [ 0-9:-]+
, on the other hand, stops consuming as soon as it sees a character that's not a space, a digit, a colon, or a hyphen.
If the next character is not [
it goes no further, and the overall match attempt fails much more quickly than it would have before. Similarly, [A-Z]+
can't blow past the closing ]
, \S+
can't overrun the next space, and [^]]+stops before the next
]. I didn't change the final
.+` because it already does what we want it to, i.e., consume all the characters until the next newline or the end of the text.
This is how I would have written the regex anyway, but just out of curiosity, what happens if you leave your regex as it is but add line anchors?
(?m)^(?:.+) \[.+?\] (.+) \[.+?\] logged in (?:.+)$
It's still hideously inefficient, but it might make the difference between not working and working badly. :D
精彩评论