在iOS中搜索带有括号的单词

时间:2013-05-30 09:38:27

标签: ios regex nsregularexpression

我正在尝试在一组文本中搜索带有括号的所有单词,并在iOS中将其更改为斜体。我正在使用此代码在文本中搜索括号:

static inline NSRegularExpression * ParenthesisRegularExpression() {
    static NSRegularExpression *_parenthesisRegularExpression = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _parenthesisRegularExpression = [[NSRegularExpression alloc] initWithPattern:@"\\[[^\\(\\)]+\\]" options:NSRegularExpressionCaseInsensitive error:nil];
    });

    return _parenthesisRegularExpression;
}

我用它来向我展示比赛:

NSRange matchRange = [result rangeAtIndex:0];
NSString *matchString = [[self.markerPointInfoDictionary objectForKey:@"long_description"] substringWithRange:matchRange];
NSLog(@"%@", matchString);

但它正在返回文本组中第一个[到最后一个]的所有文本。中间有很多括号。

我正在使用此代码将文本更改为斜体:

-(TTTAttributedLabel*)setItalicTextForLabel:(TTTAttributedLabel*)attributedLabel fontSize:(float)Size
{
    [attributedLabel setText:[self.markerPointInfoDictionary objectForKey:@"long_description"] afterInheritingLabelAttributesAndConfiguringWithBlock:^NSMutableAttributedString *(NSMutableAttributedString *mutableAttributedString)
     {
         NSRange stringRange = NSMakeRange(0, [mutableAttributedString length]);
         NSRegularExpression *regexp = ParenthesisRegularExpression();
         UIFont *italicSystemFont = [UIFont italicSystemFontOfSize:Size];
         CTFontRef italicFont = CTFontCreateWithName((__bridge CFStringRef)italicSystemFont.fontName, italicSystemFont.pointSize, NULL);
         [regexp enumerateMatchesInString:[mutableAttributedString string] options:0 range:stringRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
             NSRange matchRange = [result rangeAtIndex:0];
             NSString *matchString = [[self.markerPointInfoDictionary objectForKey:@"long_description"] substringWithRange:matchRange];
             NSLog(@"%@", matchString);
             if (italicFont) {
                 [mutableAttributedString removeAttribute:(NSString *)kCTFontAttributeName range:result.range];
                 [mutableAttributedString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)italicFont range:result.range];
                 CFRelease(italicFont);
                 NSRange range1 = NSMakeRange (result.range.location, 1);
                 NSRange range2 = NSMakeRange (result.range.location + result.range.length -2 , 1);
                 [mutableAttributedString replaceCharactersInRange:range1 withString:@""];
                 [mutableAttributedString replaceCharactersInRange:range2 withString:@""];
             }
         }];
         return mutableAttributedString;
     }];

    return attributedLabel;
}

顺便说一句,我的文字看起来像这样:

[hello] welcome [world], my [name] is [lakesh]

结果如下:

match string is [hello]
match string is [world]
match string is  is [lak

then crash..

需要一些指导来告诉我我的错误。

2 个答案:

答案 0 :(得分:7)

我没有想过你要展示的代码,但是你的正则表达似乎太贪心了:

@"\\[[^\\(\\)]+\\]"

这匹配括号“[]”之间的1-n个字符。字符由一个字符类定义,该字符类表示“除了paranthesis之外的所有字符”,即“()”除外。

换句话说,您的角色类也匹配括号字符。结果是你的表达式匹配第一个“[”和最后一个“]”之间的所有内容。

我建议您尝试使用以下正则表达式:

@"\\[[^\\[\\]]+\\]"

如果您没有嵌套括号,您甚至可以将其简化为:

@"\\[[^\\]]+\\]"

<小时/> 的修改

这是您提供的代码和示例输入文本的简化版本,但使用了我建议的正则表达式。在我的环境中,这非常有效,它会在我的调试输出窗口中打印4行。我不知道是什么原因导致你的崩溃,所以我建议你一步一步地开始简化你自己的代码,直到找到问题为止。

NSString* mutableAttributedString = @"[hello] welcome [world], my [name] is [lakesh]";
NSRange stringRange = NSMakeRange(0, [mutableAttributedString length]);
NSRegularExpression* regexp = [[NSRegularExpression alloc] initWithPattern:@"\\[[^\\]]+\\]" options:NSRegularExpressionCaseInsensitive error:nil];
[regexp enumerateMatchesInString:mutableAttributedString
                         options:0
                           range:stringRange
                      usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
 {
   NSRange matchRange = [result rangeAtIndex:0];
   NSString* matchString = [mutableAttributedString substringWithRange:matchRange];
   NSLog(@"%@", matchString);
 }
 ];

与您的代码的主要区别是:

  • 我不使用TTTAttributedLabel
  • 我不使用NSMutableAttributedString
  • 我不使用self.markerPointInfoDictionary
  • 我没有if (italicFont)代码块

所以你的问题应该是其中一个方面。

答案 1 :(得分:1)

你的崩溃日志是什么?  您是否使用原始未修改字符串的匹配范围修改字符串?如果是这样,你将在完成之前用完。

您可以考虑其他一些方法。您需要一次删除一个并停止尝试使代码在同一位置执行斜体和字符替换。那令你困惑。

你的斜体部分很好。 但是你需要通过额外的迭代逻辑来删除字符,这些逻辑在每个字符被删除后从niw较短的字符串中获得新的匹配范围。