I am trying to capture words with 3+ characters including: we've, haven't, can't etc in my string. Below works for words except above ones. Am I missing something here? Should I hit the limit of nsregularexpressions in obj-c? Should I go with NSPredicates?
NSString *currentString = aString;
// Regular expression to find all words that have greater than 3 characters
NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:#"([\\w\']{4,})"
options:0
error:NULL];
NSMutableString *modifiedString = [currentString mutableCopy];
__block int offset = 0;
[regex enumerateMatchesInString:currentString options:0 range:NSMakeRange(0, [currentString length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange range = [result rangeAtIndex:0];
// NSLog(#"range is %#", NSStringFromRange(range));
// Adjust location for modifiedString:
range.location += offset;
// Get old word:
NSString *oldWord = [modifiedString substringWithRange:range];
}
];
Related
I need to get the word that comes after a certain sign, and remove it.
example :
NSString *me=#" i am going to make !somthing great" ;
I need to remove the word something, together with the ! sign, where ever it will occur in that text.
Is there some method like stringByReplacingOccurrencesOfString: to not only find the sign ,but identify the word that attached to it ?
Thanks.
You want a regular expression. In this case, you want one with the pattern #"!\w*". (An NSScanner would also work, but I think a regular expression is more concise in this case.)
If you have reasons not to use regular expressions (or if you are not familiar with them) you can use following
NSString *me=#" i am going to make !somthing great" ;
NSRange r1 = [me rangeOfString:#"!"];
if (r1.location != NSNotFound) {
NSRange r2 = [me rangeOfCharacterFromSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]
options:0
range:NSMakeRange(r1.location, me.length - r1.location)];
if (r2.location != NSNotFound) {
me = [me stringByReplacingCharactersInRange:NSMakeRange(r1.location, r2.location - r1.location) withString:#""];
}
}
Here's code:
NSMutableString *mutableMe = [me mutableCopy];
NSError *error;
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:#"!\\w*" options:0 error:&error];
[regex replaceMatchesInString:mutableMe options:0 range:NSMakeRange(0, [mutableMe length]) withTemplate:#""];
If you want to find it first than use
[regex enumerateMatchesInString:mutableMe options:0 range:NSMakeRange(0, [mutableMe length]) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange rangeOfString = [result rangeAtIndex:0];
[mutableMe replaceCharactersInRange:rangeOfString withString:#""];
}];
Try following syntax this can help you
NSString *replacedString=[NSString stringByReplacingOccurancesOfString:#"!something" withString:#" "];
what is the best way to get and replace specific words in string ?
for example I have
NSString * currentString = #"one {two}, thing {thing} good";
now I need find each {currentWord}
and apply function for it
[self replaceWord:currentWord]
then replace currentWord with result from function
-(NSString*)replaceWord:(NSString*)currentWord;
The following example shows how you can use NSRegularExpression and enumerateMatchesInString to accomplish the task. I have just used uppercaseString as function that replaces a word, but you can use your replaceWord method as well:
EDIT: The first version of my answer did not work correctly if the replaced words are
shorter or longer as the original words (thanks to Fabian Kreiser for noting that!) .
Now it should work correctly in all cases.
NSString *currentString = #"one {two}, thing {thing} good";
// Regular expression to find "word characters" enclosed by {...}:
NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:#"\\{(\\w+)\\}"
options:0
error:NULL];
NSMutableString *modifiedString = [currentString mutableCopy];
__block int offset = 0;
[regex enumerateMatchesInString:currentString
options:0
range:NSMakeRange(0, [currentString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
// range = location of the regex capture group "(\\w+)" in currentString:
NSRange range = [result rangeAtIndex:1];
// Adjust location for modifiedString:
range.location += offset;
// Get old word:
NSString *oldWord = [modifiedString substringWithRange:range];
// Compute new word:
// In your case, that would be
// NSString *newWord = [self replaceWord:oldWord];
NSString *newWord = [NSString stringWithFormat:#"--- %# ---", [oldWord uppercaseString] ];
// Replace new word in modifiedString:
[modifiedString replaceCharactersInRange:range withString:newWord];
// Update offset:
offset += [newWord length] - [oldWord length];
}
];
NSLog(#"%#", modifiedString);
Output:
one {--- TWO ---}, thing {--- THING ---} good
I have a string like below.
<br><br><br><br><br> SomeHtmlString <br><br><br><br><br>
I want to remove br tags like trim function preserving middle br tags in SomeHtmlString.
Is there any function to do this shortly?
e.g.
<br><br><br>test1<br><br>test2<br><br><br><br>
to
test1<br><br>test2
Here is a method using regular expressions. It matches only one at a time and replaces that either at the beginning of end of the string.
NSMutableString *replaceMe = [[NSMutableString alloc ]
initWithString:#"<br><br > <br > test<br>test2<br><br>"];
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"^ *<br *> *"
options:NSRegularExpressionCaseInsensitive
error:&error];
do {
;
} while ([regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""] != 0);
regex = [NSRegularExpression
regularExpressionWithPattern:#" *<br *> *$"
options:NSRegularExpressionCaseInsensitive
error:&error];
do {
;
} while ([regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""] != 0);
NSLog(#"string=%#", replaceMe);
and that does strip "<br><br > <br > test<br>test2<br><br>" down to test<br>test2.
It's probably not the neatest solution but it is very easy to modify to match different expressions, with different whitespace, for example.
It's also possible to use the regular expressions to match several <br>s in one go:
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"^ *(<br *> *)+"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""];
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#" *(<br *> *)+$"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex replaceMatchesInString:replaceMe options:NSMatchingCompleted range:NSMakeRange(0, replaceMe.length) withTemplate:#""];
which avoids the looping but is a little harder to modify.
You can do this:
NSString* htmlString= #"<br><br><br><br><br> SomeHtmlString <br><br><br><br><br>";
NSString* pureString= [htmlString stringByReplacingOccurrencesOfString: #"<br>" withString: #""];
So you'll have #" SomeHtmlString " in pureString.
You could use this to strip out the unwanted bits:
[yourString stringByReplacingOccurrencesOfString:#"<br>" withString:#""];
Then you would use something like this to remake your string the way you want it:
NSString *newString = [NSString stringWithFormat:#"<br>%#<br>", yourString];
You might also want to look at stringByTrimmingCharactersInSet:
There are so many things you can do with NSString. Check out the Class Reference: https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
EDIT:
substringToIndex: could be your friend here. You can do this to find out if the first 4 characters of your string consist of the characters you want to remove:
NSString *subString = [yourString substringToIndex:4];
if ([subString isEqualToString:#"<br>"]) {
yourString = [yourString substringFromIndex:4];
}
Then you are creating a new string without those 4 characters. You keep doing this until the first 4 character are not equal to the ones you want to remove.
You can do something similar at the end of your string using substringFromIndex. You will need to know the length of your original string to make sure none of your substrings go out of bounds.
Alternative regular expression rendition:
NSString *input = #"<br><br><br><br><br><br>test<br>test2<br><br><br><br><br><br><br><br><br><br>";
__block NSString *output;
NSError *error;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"^(<br>)*(.*?)(<br>)*$"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex enumerateMatchesInString:input
options:0
range:NSMakeRange(0, [input length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange matchRange = [result rangeAtIndex:2];
output = [input substringWithRange:matchRange];
}];
if (output)
NSLog(#"Found: %#", output);
I'm pretty green at regex with Objective-C. I'm having some difficulty with it.
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\b([1-9]+)\\b" options:NSRegularExpressionCaseInsensitive error:®Error];
if (regError) {
NSLog(#"%#",regError.localizedDescription);
}
__block NSString *foundModel = nil;
[regex enumerateMatchesInString:self.model options:kNilOptions range:NSMakeRange(0, [self.model length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) {
foundModel = [self.model substringWithRange:[match rangeAtIndex:0]];
*stop = YES;
}];
All I'm looking to do is take a string like
150A
And get
150
First the problems with the regex:
You are using word boundaries (\b) which means you are only
looking for a number that is by itself (e.g. 15 but not 150A).
Your number range does not include 0 so it would not capture 150. It needs to be [0-9]+ and better yet use \d+.
So to fix this, if you want to capture any number all you need is \d+. If you want to capture anything that starts with a number then only put the word boundary at the beginning \b\d+.
Now to get the first occurrence you can use -[regex rangeOfFirstMatchInString:options:range:]
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\b\\d+" options:NSRegularExpressionCaseInsensitive error:®Error];
if (regError) {
NSLog(#"%#",regError.localizedDescription);
}
NSString *model = #"150A";
NSString *foundModel = nil;
NSRange range = [regex rangeOfFirstMatchInString:model options:kNilOptions range:NSMakeRange(0, [model length])];
if(range.location != NSNotFound)
{
foundModel = [model substringWithRange:range];
}
NSLog(#"Model: %#", foundModel);
What about .*?(\d+).*? ?
Demo:
That would backreference the number and you would be able to use it wherever you want.
If I have the string "Hello World", is it possible to use NSRegularExpression with the pattern #"World" to get the position of the match, i.e. in the "Hello World" example the position/index of the match should be "6"?
in php I'd use preg_match with the "PREG_OFFSET_CAPTURE" flag to achieve this, does objective-c support this?
You can do it the Cocoa way:
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:#"world" options:0 error:NULL];
// omitted error checking for the sake of simplicity
NSString *str = #"Hello world!";
[regex enumerateMatchesInString:str
options:0
range:NSMakeRange(0, str.length)
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
{
NSLog(#"Match at [%d, %d]", result.range.location, result.range.length);
}];
[regex release];
Or the POSIX way (this may be convenient for you, since you want only one match, and this function/method returns the match range directly):
#include <regex.h>
- (NSRange)matchString:(NSString *)string toRegex:(NSString *)regex
{
regex_t regex_obj;
regmatch_t match;
const char *regex_str;
const char *match_str;
int error;
regex_str = [regex UTF8String];
error = regcomp(®ex_obj, regex_str, REG_EXTENDED);
if (error)
{
return NSMakeRange(NSNotFound, 0);
}
match_str = [string UTF8String];
error = regexec(®ex_obj, match_str, 1, &match, 0);
if (error)
{
return NSMakeRange(NSNotFound, 0);
}
regfree(®ex_obj);
return NSMakeRange(match.rm_so, match.rm_eo - match.rm_so);
}
This is somewhat long in Cocoa, but you can do it:
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:#"world"
options:NSRegularExpressionSearch
error:&error];
NSString *str = #"Hello, world!";
NSTextCheckingResult *match = [regex firstMatchInString:str
options:0
range:NSMakeRange(0, [str length])];
if (match) {
NSRange matchRange = [match range];
NSLog(#"%lu", matchRange.location);
}
This prints 7.
If you're going to make a lot of use of RegEx's, I recommend looking at RegexKit or RegexKitLite.
Yes it is possible. You can use the NSRegularExpression method, rangeOfFirstMatchInString:options:range: which returns the range of the first match. You could also do this with the NSString method rangeOfString: if you don't need to use REGEX.