I have a number of NSStrings of movie titles like this:
#"Accepted (2006)"
#"Blade Runner (1982)"
#"(500) Days of Summer (2009)"
#"RoboCop (1987) - Criterion #23"
I am trying to get the four-digit numeric-only year that is always between ( and ) out of the title.
Whats the proper way to do this? NSRange? RegEx? Something else? Objective-C please, not Swift.
Use a lookaround based regex.
"(?<=\\()\\d{4}(?=\\))"
or
Use capturing group.
"\\((\\d{4})\\)"
Since (, ) are regex meta-characters, you need to escape those in-order to match the literal ( or ) symbols.
ie
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\((\\d{4})\\)" options:0 error:NULL];
NSString *str = #"Accepted (2006)";
NSTextCheckingResult *match = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];
For this it is simpler to use the NSString method: rangeOfString:options: with the option NSRegularExpressionSearch with a look-behind and look-ahead based regex:
NSRange range = [test rangeOfString:#"(?<=\\()\\d{4}(?=\\))" options:NSRegularExpressionSearch];
NSString *found = [test substringWithRange:range];
NSLog(#"found: %#", found);
Output:
found: 2006
For more information see the ICU User Guide: Regular Expressions
Related
Trying to capitalize all tags and running into trouble with substitution. Any idea why "upperCaseString" method isn't working?
NSError *error = nil;
NSMutableString *stringToCap = [NSMutableString stringWithString:#"<kaboom>stuff</kaboom>"];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"(</?[a-zA-Z].*?>)" options:NSRegularExpressionCaseInsensitive error:&error];
NSMutableString *modifiedString = [NSMutableString stringWithString:[regex stringByReplacingMatchesInString:stringToCap options:0 range:NSMakeRange(0, [stringToCap length]) withTemplate:#"$1".uppercaseString]];
NSLog(#"%#", modifiedString);
Produces: <kaboom>stuff</kaboom> when I expect <KABOOM>stuff</KABOOM>
stringByReplacingMatchesInString:options:range:withTemplate: doesn't work like that, the type of the last argument is just NSString and the string you are passing is the result of the expression #"$1".uppercaseString – which is just #"$1".
A possible algorithm (pseudo code):
for NSTextCheckingResult *match in [regex matchesInString:... options:... range:...] do
extract the substring at match.range from modified string
uppercase it
replace the substring at match.range with uppercased result
So if I have "7A7F6E88920AB8271A" and I want to split it into an array of strings with same amount of character count, like "7A", "7F", "6E", "88", ... is there any method ready for this, or I have to manually make it on objective C? Thanks.
I am not an objective-c expert, but the following might lead you in the right direction (Regular Expressions)
NSRegularExpression regexp = [NSRegularExpression
regularExpressionWithPattern:#"(\\w){2}"
options:NSRegularExpressionCaseInsensitive error:&error];
NSArray *matches = [regex matchesInString:string options:0
range:NSMakeRange(0, [string length])];
The RegExp (\\w){2}should find all 2-length character words and each of them are in the matches array.
Constructed from examples on this page: https://developer.apple.com/reference/foundation/nsregularexpression
I would like to get a substring for a NSString that contains a percentage value.
For example:
1. Get 10% off with this item.
2. 55% off when you purchase this.
function should return 10% and 55% respectively.
I am using regex in Java \\d+%
I don't know how to do the same in objective c.
I have searched it but I am a bit lost.
You should be able to use NSRegularExpression to execute the same regex that you use in java. There is a good tutorial for NSRegularExpression here.
https://www.raywenderlich.com/30288/nsregularexpression-tutorial-and-cheat-sheet
I was able to accomplish it with this code:
NSString *string = #"10% off with this item";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\d+%" options:0 error:&error];
NSTextCheckingResult *result = [regex firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
NSString *substring = [string substringWithRange:result.range];
NSLog(#"%#", substring); // 10%
The key is in the TextCheckingResult. It contains the NSRange for the match in the original string so you can grab a substring of the match.
How would I do this? I'm new to Objective-C but I can't find anything that would help me do this.
NSArray *splitLine = [currentLine componentsSeparatedByString:#":%#",notNumber];
Where notNumber is a string that represents anything that isn't a number. So I want to separate a string where there are colons separated by strings that aren't numbers. (I want to avoid splitting at times i.e. 3:00pm, but split at iCal parameters like DESCRIPTION: and LOCATION:.)
You can do this in several steps, like this. I have not compiled this code, but it should at least give you an idea of what to do.
1) Create a regex object to match your separators:
NSString *regexString = #"DESCRIPTION:\s|LOCATION:\s"; // or whatever makes sense for your scenario
NSRegularExpression *regex =
[NSRegularExpression regularExpressionWithPattern:regexString
options:NSRegularExpressionCaseInsensitive
error:nil];
2) Replace all the different separators matching your regex with just one separator:
NSRange range = NSMakeRange(0, string.length);
NSString *string2 = [regex stringByReplacingMatchesInString:string
options:0
range:range
withTemplate:#"SEPARATOR"];
3) Split the string!
NSArray *elements = [string2 componentsSeparatedByString:#"SEPARATOR"];
Shortest solution for splitting string.
NSString *str = #"Please split me to form array of words";
NSArray *wordsArray = [str componentsSeparatedByString:#" "];
You can use regular expressions!
Using the pattern (I believe this is the core of your question):
pattern = #"(?<=[^0-9]):(?=[^0-9])"
This pattern will only match ':' symbols not surrounded by numbers.
Then replace with a dummy value that won't show in your data
dummy = #"NEVERSEETHIS"
NSRegularExpressions *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
NSRange range = NSMakeRange(0, [string length])
NSString *modified= [regex replaceMatchesInString:yourString options:0 range:range withTemplate:dummy];
and finally, split
return [modified componentsSeparatedByString:dummy];
I have the following string:
NSString *string = #"she seemed \x3cem\x3ereluctant\x3c/em\x3e to discuss the matter";
I want the final string to be: "she seemed reluctant to discuss the matter"
I have the following pattern:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"/\\x[0-9a-f]{2}/"
options:NSRegularExpressionCaseInsensitive
error:&error];
NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, [string length])];
for (NSTextCheckingResult *match in matches) {
NSRange matchRange = [match range];
NSLog(#"%#", NSStringFromRange(matchRange));
}
However, I get an error saying the pattern is invalid. What am I doing wrong?
The pattern you need is:
#"\\\\x[0-9a-f]{2}"
The backslash is special to both Obj-C and the RE parser - so you need to create an Obj-C string with two \'s so the RE parser can then end up with one.
Also there are no open/close delimiters in the string - you're thinking of another programming language there!
You can save yourself some regex troubles by using the NSString method
stringByReplacingOccurrencesOfString:withString:
Or
stringByReplacingOccurrencesOfString:withString:options:range: