Getting subString from string ios? - 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];

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).

Unable to match entire regex

I would like to know whether or not a certain string has a regex.
I wrote the code below which in order to match strings similar to the following:
"A|3|a3\n"
However the code below gets an array of matches. I do not want that as I want to simply understand whether or not my response string matches the criteria given by the regex. Any suggestion on how to do so?
NSString * response = "A|3|a3\n";
NSRange searchedRange = NSMakeRange(0, [ response length]);
NSString *pattern = #"[ABC]\|[0-9]\|[a][0-9]$";
NSError *error = nil;
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern: pattern options:0 error:&error];
NSArray* matches = [regex matchesInString:response options:0 range: searchedRange];
for (NSTextCheckingResult* match in matches){
NSString* matchText = [response substringWithRange:[match range]];
NSLog(#"match: %#", matchText);
}
Xcode should throw an warning:
Warning: Unknown escape sequence '\|'
for this line:
NSString *pattern = #"[ABC]\|[0-9]\|[a][0-9]$";
"\" escape indeed the next character (to some special signification, like the classical "\n"), but "\|" is a unknown escape sequence for a normal string. So you have to "double it":
NSString *pattern = #"[ABC]\\|[0-9]\\|[a][0-9]$"
I think you are looking for a kind of an IsMatch() function. Here is an example:
NSRange matchRange = [regex rangeOfFirstMatchInString:response options:NSMatchingReportProgress range:searchedRange];
BOOL isFound = NO;
// Did we find a matching range
if (matchRange.location != NSNotFound)
isFound = YES;

NSRegularExpression not working properly

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.

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);
}
}];

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)];

Resources