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]?)$"
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 have a Regular Expression in Objective-C and I need to know how to get a certain variable...
I want to find a string that has the letter "a" somewhere in it followed by any number (including zero) of B's, C's, and D's after it and at the first non-B,C,D I want to close my search statement. Then I want to replace the A with an F and add an F to the end of my search-string.
For example: "ZYXABCBBDBCBDEJKS" would search and return: "ZYXABCBBDBCBDEJKS" ... so the string I am now working with is "ABCBBDBCBDE", I want this string to turn into this string "FBCBBDBCBDEF" and then be put back into the original string... so the final returned string will be "ZYXFBCBBDBCBDEFJKS"
I'm new to RegEx but I gave it a shot with the below objective-c code and it didn't work... I think this is because my variables on the second line of code (at the "withTemplate" part) are wrong... I shouldn't use "$2" or "$1" should I?
code:
regex = [NSRegularExpression regularExpressionWithPattern:#"A(B|C|D)*([^B|C|D])"
options:0
error:nil];
modifiedString = [regex stringByReplacingMatchesInString:myString
options:0
range:NSMakeRange(0, [htmlstring length])
withTemplate:#"F$1$2F"];
In your regex - (B|C|D)* will only capture the last matched character out of (B|C|D), since * is out of the captured group. Also, in a character class, you don't need to use a pipe to alternate, as you did in 3rd part. So, either you use character class, or you use pipe to alternate in groups. And in this particular case, I would suggest to use character class in both place.
So, you can try changing your regex to:
"A([BCD]*)([^BCD])"
ICU and Java's regular expression support (and probably other platforms) separate compilation of a regular expression from matching it to a specific string. This improves performance when a common regex pattern is matched with multiple strings, since it only needs to be compiled once.
Is there any way to do this with NSRegularExpression? Its design appears to combine these two steps, if I'm reading the documentation correctly.
They are two steps. First, you create a regular expression:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"<h1>(.*?)</h1>"
options:NSRegularExpressionCaseInsensitive
error:&error];
And then, second, you use it (obviously use whatever method you want):
[regex enumerateMatchesInString:htmlString
options:0
range:NSMakeRange(0, [htmlString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
// do whatever you want
}];
Am I misunderstanding the question?