Reputation: 1314
Hi i have somehow a complex regex situation.
mainString = @"Main Term (Rounded) [Square] ~a~d~j~."
I need this to be returned like
modifiedString* = @"Main Term (Rounded) [Square] adj."
So every char after ~
must be italic or whatever attribute.
And I need the range for "adj."
after modification so that I can add Attribtues.
Thank You.
NSError *error3 = nil;
NSRegularExpression *SHRegex = [NSRegularExpression regularExpressionWithPattern:@"\\~(.|)" options:0 error:&error3];
NSArray *matches3 = [SHRegex matchesInString:mainString options:0 range:NSMakeRange(0, [mainString length])];
NSUInteger *numberOfMatches = [SHRegex numberOfMatchesInString:mainString options:0 range:NSMakeRange(0, mainString.length)];
NSString *modifiedString = [SHRegex stringByReplacingMatchesInString:mainString options:0 range:NSMakeRange(0, [string length]) withTemplate:@""];
for (NSTextCheckingResult *match in matches3) {
NSRange matchRange = [match range];
NSRange firstHalfRange = [match rangeAtIndex:1];
//NSRange secondHalfRange = [match rangeAtIndex:2];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0 green:0 blue:0 alpha:1] range:matchRange];
//[string addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:firstHalfRange];
}
Upvotes: 0
Views: 181
Reputation: 539685
The following code should do what you want. It creates an attributed string where the tilde characters are removed, and an attribute is added to the character following the tilde. I have added some comments which hopefully explain how it works.
NSString *mainString = @"Main Term (Rounded) [Square] ~a~d~j~.";
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:mainString];
NSError *error = nil;
// Pattern that matches a tilde followed by an arbitrary character:
NSString *pattern = @"(\\~)(.)";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
__block NSUInteger offset = 0;
[regex enumerateMatchesInString:mainString options:0 range:NSMakeRange(0, [mainString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange firstHalfRange = [result rangeAtIndex:1]; // range of the tilde
NSRange secondHalfRange = [result rangeAtIndex:2]; // range of the following character
// Adjust locations according to the string modifications:
firstHalfRange.location += offset;
secondHalfRange.location += offset;
// Set attribute for the character:
[attrString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:1 green:0 blue:0 alpha:1] range:secondHalfRange];
// Remove the tilde:
[[attrString mutableString] deleteCharactersInRange:firstHalfRange];
// Update offset:
offset -= firstHalfRange.length;
}];
Update in response to your comment: The following code matches two patterns (tilde or caret followed by a character) and uses different attributes for the replacement.
NSString *mainString = @" ~a^b~c^d";
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:mainString];
NSError *error = nil;
NSString *pattern = @"(\\~|\\^)(.)";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
__block NSUInteger offset = 0;
[regex enumerateMatchesInString:mainString options:0 range:NSMakeRange(0, [mainString length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSRange firstHalfRange = [result rangeAtIndex:1];
NSRange secondHalfRange = [result rangeAtIndex:2];
NSString *firstMatch = [mainString substringWithRange:firstHalfRange];
// Adjust locations according to the string modifications:
firstHalfRange.location += offset;
secondHalfRange.location += offset;
// Set color attribute for the character:
if ([firstMatch isEqualToString:@"~"]) {
[attrString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:1 green:0 blue:0 alpha:1] range:secondHalfRange];
} else {
[attrString addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:0 green:1 blue:0 alpha:1] range:secondHalfRange];
}
[[attrString mutableString] deleteCharactersInRange:firstHalfRange];
// Update offset:
offset -= firstHalfRange.length;
}];
Upvotes: 1
Reputation: 9591
Does your regex implementation support positive lookbehind?
If so, you could use (?<=~)(.)
to match a
, d
, j
and .
separately.
Upvotes: 0