how to alter a string with NSRegularExpression - objective-c

I am a beginner in objective-c.
I have the following NSMutableString stringVal=#"[abc][test][end]";
What is the best way I should use in order to REMOVE THE LAST [] piece (e.g [end])?
I have this code:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\[]" options:0 error:NULL];
NSArray *matches = [regex matchesInString:stringVal options:0 range:NSMakeRange(0, [stringVal length])];
for (NSTextCheckingResult *match in matches) {
?? what should i do here?
}

I think you should use this regular expression pattern "\\[.*?]" then you get three matches
['[abc]', '[test]', '[end]']
then can just get the range of the third match (check that you have at least three)
NSMutableString* stringVal= [NSMutableString stringWithString:#"[abc][test][end]"];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\[.*?]" options:0 error:NULL];
NSArray *matches = [regex matchesInString:stringVal options:0 range:NSMakeRange(0, [stringVal length])];
NSTextCheckingResult* match = matches[2];
NSMutableString* substring = [[stringVal substringToIndex:match.range.location] mutableCopy];

jbat was right that you should modify the regex. After that, all you need is the last match, so you could use
NSTextCheckingResult *match = [matches lastObject]; // Get the last match
NSRange matchRange = [match range]; // Get the position of the match segment
NSString *result = [stringVal stringByReplacingCharactersInRange:matchRange withString:#""]; // Replace the segment by an empty string.

Related

How can I replace strings between a pattern for an NSString?

Consider an NSString of the following pattern:
(foo('Class 0')bar('Class 1')baz('Class 2')
I just need to return foo, bar and baz. Any way I could at least replace 'Class 0' to some single character using regex?
I tried:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\(.*?\\)"
options:NSRegularExpressionCaseInsensitive
error:nil];
text = [regex stringByReplacingMatchesInString:text options:0 range:NSMakeRange(0, [text length]) withTemplate:#""];
If I understood your situation correctly, you needed to parse foo, bar, and baz out of the string above. The code below will do just that, and return foo, bar, and baz in an array.
As you will see in the code, we match on a word and an opening paren, and then trim the parens off programmatically. There may be a better regex that doesn't require the trimming, but I couldn't make that work with NSRegularExpression.
NSString *text = #"(foo('Class 0')bar('Class 1')baz('Class 2')";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[a-z]+[\(]"
options:NSRegularExpressionCaseInsensitive
error:nil];
NSMutableArray *output = [[NSMutableArray alloc] init];
[regex enumerateMatchesInString:text
options:0
range:NSMakeRange(0, [text length])
usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) {
NSString *rawMatch = [text substringWithRange:result.range];
NSString *trimmed = [rawMatch substringToIndex:(rawMatch.length - 1)];
[output addObject:trimmed];
}];
To get a string, like the one you mention in your comment above, just use
NSString *finalString = [output componentsJoinedByString:#" "];
I would just use:
NSString *string = #"foo('Class 0')bar('Class 1')baz('Class 2')";
NSString *output = [string stringByReplacingOccurrencesOfString:#"\\('[^')]*'\\)"
withString:#" "
options:NSRegularExpressionSearch
range:NSMakeRange(0, string.length)];
NSLog(#"%#", output); // foo bar baz
Replacing anything between (' and ') with a space. The pattern [^')] means that we don't want ) and 'letters to appear in between.

Trim an NSString Based Upon Number Of Character Occurrences

I'm trying to trim an NSString after I detect 3 new line instances. (\n). So, this is what I've tried:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\n" options:NSRegularExpressionCaseInsensitive error:&error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [myString length])];
Now, number of matches will always exceed 3, and I want to stop the string right as it hits the third \n. Does any one know any good logic to do this?
If the 3 new line instances are always grouped together it's pretty easy:
NSString *testString = #"The quick brown fox jumps \n\n\n over the lazy dog. \n\n\n New Line.";
[[string componentsSeparatedByString:#"\n\n\n"] firstObject]
Otherwise you could use:
NSError *error;
NSString *pattern = #"(\\A|\\n\\s*\\n\\s*\\n)(.*?\\S[\\s\\S]*?\\S)(?=(\\Z|\\s*\\n\\s*\\n\\s*\\n))";
NSRegularExpression* regex = [[NSRegularExpression alloc] initWithPattern:pattern
options:NSRegularExpressionCaseInsensitive
error:&error];
[regex enumerateMatchesInString:testString
options:0
range:NSMakeRange(0, [testString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSString *match = [testString substringWithRange:[result rangeAtIndex:2]];
NSLog(#"match = '%#'", match);
}];
(Taken from this answer)
NSString* originalString = #"This\nis\na\ntest string";
NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:#".*\\n.*\\n.*\\n" options:0 error:nil];
NSRange range = [regex rangeOfFirstMatchInString:originalString options:0 range:(NSRange){0,originalString.length}];
NSString* trimmedString = [originalString substringFromIndex:range.length];
NSLog(#"Original: %#", originalString);
NSLog(#"Trimmed: %#", trimmedString);
Prints:
2015-02-05 21:39:41.491 TestProject[4258:1269568] Original: This
is
a
test string
2015-02-05 21:39:41.492 TestProject[4258:1269568] Trimmed: test string

objective-C subranging a word that starts with

I want to substring a word that starts with '#'.
Using rangeOfString will only give me the start of the word and then searching again for ' '.
There must be a more elegant way, right?
I'm all for NSRegularExpression for this situation. This is a good starting point for you.
NSString *string = #"Hello #world how are #you?";
// Find all words beginning with an '#' symbol.
NSRegularExpression *expression = [NSRegularExpression regularExpressionWithPattern:#"#(\\w+)"
options:0
error:NULL];
for (NSTextCheckingResult *result in [expression matchesInString:string
options:0
range:NSMakeRange(0, [string length])])
{
NSLog(#"%#", [string substringWithRange:[result rangeAtIndex:1]]);
}

how to use regular expressions NSRegularExpression for an NSMutableArray

I have the following code which works:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[a-cA-C2][m-oM-O][a-cA-C2]" options:0 error:NULL];
NSString *str = #"Ana";
NSTextCheckingResult *match1 = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];
NSLog(#"check is exist: %#", [str substringWithRange:[match1 rangeAtIndex:0]]);
Here are my questions:
1.Is there a way I can change the NSString with an NSMutableArray and save the NSTextCheckingResult in a NSMutableArray called filterArray?
2.How to highlight the matching values when displaying then in a TextField?
If I correctly understand your question,
you want to use NSArray of strings, and receive NSArray of matching results for each string.
So, 1:
NSArray *arrayOfStrings = /* Your array */;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[a-cA-C2][m-oM-O][a-cA-C2]" options:0 error:NULL];
NSMutableArray *filterArray = [NSMutableArray array];
[arrayOfStrings enumerateObjectsUsingBlock:^(NSString * str, NSUInteger idx, BOOL * stop) {
NSTextCheckingResult *match = [regex firstMatchInString:str options:0 range:NSMakeRange(0, [str length])];
if (match) {
[filterArray addObject:match];
}
else {
[filterArray addObject:[NSNull null]];
}
NSLog(#"String #%i. check is exist: %#",idx, [str substringWithRange:[match rangeAtIndex:0]]);
}];
2: For highlighting ranges of the string you need to use NSAttributedString. Please, see this question for the answer how:) How do you use NSAttributedString?
After you formed attributed string, set it to textfield:
NSAttributedString * attributedString;
UITextField *textField;
[ttextField setAttributedText:attributedString];

regex to extract all the substrings between two characters or tags

I need to extract all the strings surrounded by two characters (or maybe two tags)
this is what I've done so far:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\[(.*?)\\]" options:NSRegularExpressionCaseInsensitive error:NULL];
NSArray *myArray = [regex matchesInString:#"[db1]+[db2]+[db3]" options:0 range:NSMakeRange(0, [#"[db1]+[db2]+[db3]" length])] ;
NSLog(#"%#",[myArray objectAtIndex:0]);
NSLog(#"%#",[myArray objectAtIndex:1]);
NSLog(#"%#",[myArray objectAtIndex:2]);
In myArray there are correctly three objects but NSlog prints this:
<NSSimpleRegularExpressionCheckingResult: 0x926ec30>{0, 5}{<NSRegularExpression: 0x926e660> \[(.*?)\] 0x1}
<NSSimpleRegularExpressionCheckingResult: 0x926eb30>{6, 5}{<NSRegularExpression: 0x926e660> \[(.*?)\] 0x1}
<NSSimpleRegularExpressionCheckingResult: 0x926eb50>{12, 5}{<NSRegularExpression: 0x926e660> \[(.*?)\] 0x1}
instead of db1, db2 and db3
where I'm wrong?
According to the documentation matchesInString:options:range: returns an array of NSTextCheckingResults not NSStrings. You will need to loop over the results and use the ranges to get the substrings.
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"\\[(.*?)\\]" options:NSRegularExpressionCaseInsensitive error:NULL];
NSString *input = #"[db1]+[db2]+[db3]";
NSArray *myArray = [regex matchesInString:input options:0 range:NSMakeRange(0, [input length])] ;
NSMutableArray *matches = [NSMutableArray arrayWithCapacity:[myArray count]];
for (NSTextCheckingResult *match in myArray) {
NSRange matchRange = [match rangeAtIndex:1];
[matches addObject:[input substringWithRange:matchRange]];
NSLog(#"%#", [matches lastObject]);
}
Or this
NSArray *results = [#"[db1]+[db2]+[db3]" matchWithRegex:#"\\[(.*?)\\]"];
//result = #["db1","db2,"db3"]
With this category https://github.com/damienromito/NSString-Matcher