I'm building a regular expression for use in a parser in an iOS app. Here's my code:
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:#"(?<=#EXT[^\r\n]*[\r\n]+)[^#][^\r\n]+"
options:NSRegularExpressionAnchorsMatchLines
error:®exError
];
if (regexError) {
NSLog(#"regexError: %#", regexError);
return nil;
}
From this answer.
This gives out this error:
regexError: Error Domain=NSCocoaErrorDomain Code=2048 "The operation couldn’t be completed. (Cocoa error 2048.)" UserInfo=0x8e86670 {NSInvalidValue=(?<=#EXT[^
Cocoa error 2048 is an NSFormattingErrorMinimum according to the docs... But there's literally no further explanation.
What does it mean?
are you trying to match a new line/line feed character? you've inserted a literal new line character into your regex... you need to instead insert the code for a newline. Try escaping as \\n etc.
edit:
You have to escape all special strings. For example you want your regex string to contain \+r, not a linefeed character. So you need to use \\r instead of \r.
i.e.
"(?<=#EXT[^\\r\\n]*[\\r\\n]+)[^#][^\\r\\n]+"
edit 2:
You cannot have unlimited length strings in your look-behind. So, no * and no + allowed. This is per the ICU regex reference. (NSRegularExpression uses ICU regex syntax.)
Related
I'm building a regular expression for use in a parser in an iOS app. Here's my code:
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:#"(?<=#EXT[^\r\n]*[\r\n]+)[^#][^\r\n]+"
options:NSRegularExpressionAnchorsMatchLines
error:®exError
];
if (regexError) {
NSLog(#"regexError: %#", regexError);
return nil;
}
From this answer.
This gives out this error:
regexError: Error Domain=NSCocoaErrorDomain Code=2048 "The operation couldn’t be completed. (Cocoa error 2048.)" UserInfo=0x8e86670 {NSInvalidValue=(?<=#EXT[^
Cocoa error 2048 is an NSFormattingErrorMinimum according to the docs... But there's literally no further explanation.
What does it mean?
are you trying to match a new line/line feed character? you've inserted a literal new line character into your regex... you need to instead insert the code for a newline. Try escaping as \\n etc.
edit:
You have to escape all special strings. For example you want your regex string to contain \+r, not a linefeed character. So you need to use \\r instead of \r.
i.e.
"(?<=#EXT[^\\r\\n]*[\\r\\n]+)[^#][^\\r\\n]+"
edit 2:
You cannot have unlimited length strings in your look-behind. So, no * and no + allowed. This is per the ICU regex reference. (NSRegularExpression uses ICU regex syntax.)
Backgroud:
I have a response like so (please note the new lines):
HTTP/1.1 200 OK
CACHE-CONTROL: max-age = 180
EXT:
LOCATION: http://172.16.16.16:80/upnp.jsp
SERVER: Linux/2.6.32.24 UPNP/1.0 ZD3025/9.5.1.0
ST: upnp:rootdevice
USN: uuid:6e4bb543-fff6-4384-a4be-::upnp:rootdevice
I would like to match the Server line which is:
Linux/2.6.32.24 UPNP/1.0 ZD3025/9.5.1.0
Implementation:
I don't care about any character in the above given response EXCEPT for the characters Linux, UPNP and ZD (in that order).
So I am using .* to match any number of characters, numbers, special chars.
-(void) regexCompareForUPnP:(NSString *) string {
NSError * err = nil;
//Building expression
NSString *expression = #"^.*Linux.*UPNP.*ZD.*$";
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:expression options:0 error:&err];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string
options:0
range:NSMakeRange(0, [string length])];
NSLog(#"Matches found: %d", numberOfMatches);
}
So far, Matches found: 0.
Question:
So, in short does this:
NSString *expression = #"^.*Linux.*UPNP.*ZD.*$";
Match this:
Linux/2.6.32.24 UPNP/1.0 ZD3025/9.5.1.0
EDIT:
Thank you omz that worked perfectly.
Now I am trying to match the upnp.jsp (in the LOCATION line) alongwith what I was trying to match before. So I tried this:
NSString *expression = #"^.*upnp.jsp\n.*Linux.*UPNP.ZD.$";
That does not work. Appreciate your help..
I'm not familiar with this regex library. Based on what you're trying to match, however, it may be to do with newlines between OS's and individual programs.
Try this: *expression = #"upnp.jsp\r?\n[^\n]*?Linux[^\n]*?UPNP[^\n]*?ZD"
A few other changes made from what you're trying as well;
I've replaced .* with [^\n]*? for two reasons:
I'm not sure how this library deals with .*, but using that is typically inefficient in comparison to something more speicific such as looking for a non-greedy set of characters that aren't a new line. The difference between .* and .*? depends on the regex engine. In most regex engines I work with at least, .* is by default greedy; i.e. it will capture as much data as it can while still having the expression find a match. Using the non-greedy version, .*?, means that the regex will capture only as much as it needs to to satisfy the whole expression. This is particularly evident in an example I'll expand on at the end.
I removed the surrounding ^$ because when they are appended and prepended with .* they only work towards increasing processing time (unless you were using matching groups, which you aren't). If you were doing ^(.*)upnp or ^(.*upnp) and then using the contents of the matched group, there could be purpose in having the initial ^.*.
As for greedy/non-greedy, the difference becomes evident when trying to match data between a set of double quotes ". For the sake of simplicity, I won't deal with having escaped double quotes in the middle of a string you also want to capture.
Given the string: I said, "Hi." She responded with, "Hello!"
Using the greedy regex "(.*)", the matched group would be Hi." She responded with, "Hello!
Using the non-greedy regex "(.*?)", the matched group would be Hi.
I've got this regex
([0-9]+)\(([0-9]+),([0-9]+)\)
that I'm using to construct a NSRegularExpression with no options (0). That expression should match strings like
1(135,252)
and yield three matches: 1, 135, 252. Now, I've confirmed with debuggex.com that the expression is correct and does what I want. However, iOS refuses to acknowledge my efforts and the following code
NSString *nodeString = #"1(135,252)";
NSArray *r = [nodeRegex matchesInString:nodeString options:0 range:NSMakeRange(0, nodeString.length)];
NSLog(#"--- %#", nodeString);
for(NSTextCheckingResult *t in r) {
for(int i = 0; i < t.numberOfRanges; i++) {
NSLog(#"%#", [nodeString substringWithRange:[t rangeAtIndex:i]]);
}
}
insists in saying
--- 1(135,252)
135,252
13
5,252
5
252
which is clearly wrong.
Thoughts?
Your regex should look like this
[NSRegularExpression regularExpressionWithPattern:#"([0-9]+)\\(([0-9]+),([0-9]+)\\)"
options:0
error:NULL];
Note the double backslashes in the pattern. They are needed because the backslash is used to escape special characters (like for example quotes) in C and Objective-C is a superset of C.
If you are looking for a handy tool for working with regular expressions I can recommend Patterns. Its very cheap and can export straight to NSRegularExpressions.
Debuggex currently supports only raw regexes. This means that if you are using the regex in a string, you need to escape your backslashes, like this:
([0-9]+)\\(([0-9]+),([0-9]+)\\)
Also note that Debuggex does not (yet) support Objective C. This probably won't matter for simple regexes, but for more complicated ones, different engines do different things. This can result in some unexpected behavior.
I am working on an iOS project that require using regular expression to validate ipv4 address.
I use following code
// only support ip4 currently
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
options:0
error:nil];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:IpString options:0 range:NSMakeRange(0, [IpString length])];
return (numberOfMatches==1?TRUE:FALSE);
XCode keep warning me "unknown escape sequence .". When return true when I type "1.3.6.-6" or "2.3.33".
How can I use dot(.) in regex? Thanks
You need to double backslash your ., as the first backslash is being interpreted by NSString, and it's looking for an escape character for . (which doesn't exist). Double backslashing (\\.) will cause the first backslash to escape the second backslash (which does exist), meaning you can use \ normally.
So for example, your regex will be:
#"^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"
i've tried to read the apple documentation but i'll never use regular expression and i do not understand how to solve this matter.
I need to write a regular expression for check if the user has selected a string that match with this rules:
first letter could be s or S and it's optional
second chars could be a . (char dot) and it's optional
4 number digit could from 1 to 4 and must be always present
after the number could be present any single char from a-z and could be optional
after i can have a . (char dot) and it's optional
the last 2 must be a digit must be always 2 number and could be optional
i tried to write in this way
NSString *regexStr = #"(s|S)?(\\.)?(\\d+){,4}([a-z]?(\\.)?(\\d+){2}?";
but the console give this error
Error making regex: Error Domain=NSCocoaErrorDomain Code=2048
"The operation couldn’t be completed. (Cocoa error 2048.)" UserInfo=0x6d3e9b0
{NSInvalidValue=(s|S)?(\.)?(\d+){,4}([a-z]?(\.)?(\d+){2}?}
Anyone could help me?
Thanks!
Here you go:
(s|S)?(\.)?(\d){0,4}[a-z]?(\.)?(\d){2}?
You had an extra opening parenthesis that made the syntax invalid, and + signs after the \ds, that made the regexp accept infinite numbers of digits.
Regexpal is great for debugging regexps: http://regexpal.com/