NSRegularExpression not working properly - ios

Hi i'm having problems where if in the string the there isn't a phone number and the NSRegularExpression cant find anything the app crashes but when it does find the phone number it in the string its works fine with no problems. How can i stop it from crashing.
NSRegularExpression *phoneexpression = [NSRegularExpression regularExpressionWithPattern:#"\\d{4}-\\d{4}"options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *phString = TextString;
NSString *PH = [phString substringWithRange:[phoneexpression rangeOfFirstMatchInString:phString options:NSMatchingCompleted range:NSMakeRange(0, [phString length])]];
I think this is the problem
NSString *PH = [phString substringWithRange:[phoneexpression rangeOfFirstMatchInString:phString options:NSMatchingCompleted range:NSMakeRange(0, [phString length])]];

I guess you get a NSRangeException.
Try it this way:
NSString *PH = nil;
NSRegularExpression *phoneexpression = [NSRegularExpression regularExpressionWithPattern:#"\\d{4}-\\d{4}"options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *phString = TextString;
NSRange rg = [phoneexpression rangeOfFirstMatchInString:phString options:NSMatchingCompleted range:NSMakeRange(0, [phString length])];
if(rg.location != NSNotFound)
PH = [phString substringWithRange:rg];
It is important that you check the returned range before passing it to substringWithRange.
See this reference for more information: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/#//apple_ref/occ/instm/NSString/substringWithRange:
EDIT:
Also check that the returned range from rangeOfFirstMatchInString does not violate the boundary limitations documented in the reference:
Raises an NSRangeException if (aRange.location - 1) or
(aRange.location + aRange.length - 1) lies beyond the end of the
receiver.

Related

Objective C - NSRegularExpression with specific substring

I have an NSString which I am checking if there is an NSLog and then I comment it out.
I am using NSRegularExpression and then looping through result.
The code:
-(NSString*)commentNSLogFromLine:(NSString*)lineStr {
NSString *regexStr =#"NSLog\\(.*\\)[\\s]*\\;";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexStr options:NSRegularExpressionCaseInsensitive error:nil];
NSArray *arrayOfAllMatches = [regex matchesInString:lineStr options:0 range:NSMakeRange(0, [lineStr length])];
NSMutableString *mutStr = [[NSMutableString alloc]initWithString:lineStr];
for (NSTextCheckingResult *textCheck in arrayOfAllMatches) {
if (textCheck) {
NSRange matchRange = [textCheck range];
NSString *strToReplace = [lineStr substringWithRange:matchRange];
NSString *commentedStr = [NSString stringWithFormat:#"/*%#*/",[lineStr substringWithRange:matchRange]];
[mutStr replaceOccurrencesOfString:strToReplace withString:commentedStr options:NSCaseInsensitiveSearch range:matchRange];
NSRange rOriginal = [mutStr rangeOfString:#"NSLog("];
if (NSNotFound != rOriginal.location) {
[mutStr replaceOccurrencesOfString:#"NSLog(" withString:#"DSLog(" options:NSCaseInsensitiveSearch range:rOriginal];
}
}
}
return [NSString stringWithString:mutStr];
}
The problem is with the test case:
NSString *str = #"NSLog(#"A string"); NSLog(#"A string2")"
Instead of returning "/*DSLog(#"A string");*/ /*DSLog(#"A string2")*/" it returns: "/*DSLog(#"A string"); NSLog(#"A string2")*/".
The issue is how the Objective-C handles the regular expression. I would expected 2 results in arrayOfAllMatches but instead that I am getting only one. Is there any way to ask Objective-C to stop on the first occurrence of ); ?
The problem is with the regular expression. You are searching for .* inside the parentheses, which causes it to include the first close parenthesis, continue through the second NSLog statement, and go all the way to the final close parentheses.
So what you want to do is something like this:
NSString *regexStr =#"NSLog\\([^\\)]*\\)[\\s]*\\;";
That tells it to include everything inside the parenthesis except for the ) character. Using that regex, I get two matches. (note that you omitted the final ; in your string sample).

iOS: extract substring of NSString in objective C

I have an NSString as:
"<a href='javascript:void(null)' onclick='handleCommandForAnchor(this, 10);return false;'>12321<\/a>"
I need to extract the 12321 near the end of the NSString from it and store.
First I tried
NSString *shipNumHtml=[mValues objectAtIndex:1];
NSInteger htmlLen=[shipNumHtml length];
NSString *shipNum=[[shipNumHtml substringFromIndex:htmlLen-12]substringToIndex:8];
But then I found out that number 12321 can be of variable length.
I can't find a method like java's indexOf() to find the '>' and '<' and then find substring with those indices. All the answers I've found on SO either know what substring to search for or know the location if the substring. Any help?
I don't usually advocate using Regular expressions for parsing HTML contents but it seems a regex matching >(\d+)< would to the job in this simple string.
Here is a simple example:
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#">(\\d+)<"
options:0
error:&error];
// Handle error != nil
NSTextCheckingResult *match = [regex firstMatchInString:string
options:0
range:NSMakeRange(0, [string length])];
if (match) {
NSRange matchRange = [match rangeAtIndex:1];
NSString *number = [string substringWithRange:matchRange]
NSLog(#"Number: %#", number);
}
As #HaneTV says, you can use the NSString method rangeOfString to search for substrings. Given that the characters ">" and "<" appear in multiple places in your string, so you might want to take a look at NSRegularExpression and/or NSScanner.
that may help on you a bit, I've just tested:
NSString *_string = #"<a href='javascript:void(null)' onclick='handleCommandForAnchor(this, 10);return false;'>12321</a>";
NSError *_error;
NSRegularExpression *_regExp = [NSRegularExpression regularExpressionWithPattern:#">(.*)<" options:NSRegularExpressionCaseInsensitive error:&_error];
NSArray *_matchesInString = [_regExp matchesInString:_string options:NSMatchingReportCompletion range:NSMakeRange(0, _string.length)];
[_matchesInString enumerateObjectsUsingBlock:^(NSTextCheckingResult * result, NSUInteger idx, BOOL *stop) {
for (int i = 0; i < result.numberOfRanges; i++) {
NSString *_match = [_string substringWithRange:[result rangeAtIndex:i]];
NSLog(#"%#", _match);
}
}];

Getting subString from string ios?

I have a following string in iOS :-
[{"status":"0","eventid":"126"}]15.511563,73.809732[{"status":"0"}]
And I am trying to fetch this :-
[{"status":"0","eventid":"126"}]
i.e. the entire portion of string before first ] closing bracket.
I tried this in which I get a substring of 31 characters, but this won't work if the contents between the brackets changes.
NSRange start = [result1 rangeOfString:#"["];
NSString *shortString =[result1 substringWithRange:NSMakeRange(start.location, 31)];
result1 = [result1 substringToIndex:shortString.length];
NSLog(#"Response- %#",result1);
What is the correct approach?
Just like you are getting the start range (NSRange start = [result1 rangeOfString:#"["];), also get the end range:
NSRange end = [result1 rangeOfString:#"]"];
Now you have enough information to extract the substring:
NSString *result = [result1 substringWithRange:NSMakeRange(start.location, end.location - start.location)];
In your current code, you don't need to use substring... methods twice as you have already extracted the string you want in the first call. Making the second call is just ignoring the bit of code which found the start location and assuming that you always want the substring from the start of the string, which is less flexible.
Make the END Range also
NSRange start;
NSRange end;
start = [result1 rangeOfString: #"["];
end = [result1 rangeOfString: #"]"];
NSString *newResult = [result1 substringWithRange:NSMakeRange(start.location+1, end.location)];
NSLog(#"%#", newResult);
You could try using a NSRegularExpression:
NSError *error = NULL;
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:#"\\[(.*?)\\]"
options:NSRegularExpressionCaseInsensitive
error:&error];
Now, search for the first match:
NSString *string = #"[{\"status\":\"0\",\"eventid\":\"126\"}]15.511563,73.809732[{\"status\":\"0\"}]";
NSTextCheckingResult *match =
[regex firstMatchInString:string
options:0
range:NSMakeRange(0, [string length])];
Now you can get the range for the capture group:
NSRange block = [match rangeAtIndex:1];

NSString Substring detection

I need help with replacing occurrences of string with another string. Occurrency that needs to be detected is actually some kind of function:
%nx+a or %nx-a
where x and a are some numbers.
So for example %n10+2 or %n54-11.
I can't even use something like:
NSRange startRange = [snippetString rangeOfString:#"%n"];
because if I have two patterns within same string I'm checking I'll only get starting range of first one...
Thanks.
For something like this you could use an NSRegularExpression and use the method enumerateMatches:.
Or you can create your own loop.
The first is the easiest once you have the correct pattern.
Something like...
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"%n" options:0 error:nil];
NSString *string = #"%n10+2*%n2";
[regex enumerateMatchesInString:string
options:0
range:NSMakeRange(0, string.length)
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
// here you will get each instance of a match to the pattern
}];
You will have to check the docs for NSRegularExpression to learn how to do what work you need to do with this.
Docs... https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html
I assume that you need to do something with those two numbers. I think the best way is to use a regular expression to extract what you need in one go.
NSString * string = #"some %n5-3 string %n11+98";
NSError * regexError = nil;
NSRegularExpression * regex = [NSRegularExpression regularExpressionWithPattern:#"%n(\\d+)([+-])(\\d+)"
options:0
error:&regexError];
NSArray * matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)];
for (NSTextCheckingResult * match in matches) {
NSString * firstNumber = [string substringWithRange:[match rangeAtIndex:1]];
NSString * secondNumber = [string substringWithRange:[match rangeAtIndex:3]];
NSString * sign = [string substringWithRange:[match rangeAtIndex:2]];
// Do something useful with the numbers.
}
Of course if you just need to replace all the %n occurences with a constant string you can do that in one call:
NSString * result = [string stringByReplacingOccurrencesOfString:#"%n\\d+[+-]\\d+"
withString:#"here be dragons"
options:NSRegularExpressionSearch
range:NSMakeRange(0, string.length)];
Disclaimer: I didn't test this code. Minor bugs may be present.
Alter this code to match ur need
yourString = [yourString stringByReplacingOccurrencesOfString:#" +" withString:#" "options:NSRegularExpressionSearch range:NSMakeRange(0, yourString.length)];

stringByReplacingOccurrencesOfString function

I am new to ios development.
NSString *newString2 = [aString stringByReplacingOccurrencesOfString:#"1," withString:#""];
My problem is i do not know how to check for any number i.e. stringByReplacingOccurrencesOfString:#"anyInt," where any Int is any integer number from 1 to N.
Thanks in advance!
Using regular expressions is the best solution:
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[1-9]" options:NSRegularExpressionCaseInsensitive error:&error];
NSString *modifiedString = [regex stringByReplacingMatchesInString:string options:0 range:NSMakeRange(0, [string length]) withTemplate:#""];
Check official NSRegularExpression documentation, there is also a good tutorial here
A regular expression is probably the easiest solution. Whether you want to remove just single digits or multiple digits, a regular expression can help.
NSString *aString = #"Apple 10, Banana 3, Carrot 5, Durian 42, Eggplant 4,";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[0-9]+," options:0 error:NULL];
NSString *newString = [regex stringByReplacingMatchesInString:aString options:0 range:NSMakeRange(0, [aString length]) withTemplate:#""];
NSLog(#"%#", newString);
// result should be "Apple Banana Carrot Durian Eggplant "
Regular expressions may seem overwhelming or difficult to understand at first, but it is only because they can be very powerful for searching and replacing text. Have a look at the overview section of the NSRegularExpression documentation for more information.
For nos in first part greater than 0, second part is shown. For 0 in first part, -- is shown.
Try the below code,
NSString * aString = #"1,10";
NSString *newString2;
NSArray *items = [aString componentsSeparatedByString:#","];
if([[items objectAtIndex:0] integerValue]>0)
newString2 = [items objectAtIndex:1];
else
newString2 = #"--";
Just these two lines to remove all numbers from a string.
NSCharacterSet *numbers = [NSCharacterSet
characterSetWithCharactersInString:#"0123456789"];
NSString *newString = [[tempstr componentsSeparatedByCharactersInSet: numbers] componentsJoinedByString:#""];
If you want to check the range and then you want to replace then use below api:-
- (NSString *)stringByReplacingCharactersInRange:(NSRange)range withString:(NSString *)replacement
why you want to check the existence of the Integer because ultimate you'll replace it with ''. So just use the below line
NSString *newString2 = [aString stringByReplacingOccurrencesOfString:[NSString StringWithFormat:#"%d", anyInt], withString:#""];
Above line will fulfill your requirement.

Resources