正则表达式,仅选择特殊字符包围的单词

时间:2018-03-10 10:42:43

标签: ios objective-c regex

我想编写一个函数,它接受一个字符串并更改特殊字符中所有单词的颜色。例如:

  

这是包含[样本字]

的[Sample]字符串

我想在上面的字符串中更改[Sample][sample words]的字体,因为它们都被特殊字符[ ]包围。

我尝试使用以下功能制作该功能:

NSMutableAttributedString * string = [[NSMutableAttributedString alloc]initWithString:_txtPostDiscussion.text];

NSArray *words=[_txtPostDiscussion.text componentsSeparatedByString:@" "];
for (NSString *word in words) {
    if ([word hasPrefix:@"["] && [word hasSuffix:@"]"] ) {
        NSRange range=[_txtPostDiscussion.text rangeOfString:[NSString stringWithFormat:@"%@ %@",pre,suf]];
        [string addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithRed:107.0/255.0 green:148.0/255.0 blue:187.0/255.0 alpha:1.0] range:range];

        [_txtPostDiscussion setAttributedText:string];
    }
}

我也尝试使用Regex将所有单词都包含在特定的特殊字符中,但是我无法进行这样的正则表达式。

2 个答案:

答案 0 :(得分:2)

如果您想匹配[Sample maybe some _special_ *things* here],我们首先需要找到起始[。这个括号对正则表达式有特殊的意义,因此在正则表达式中它必须是"装饰" (转义)使用反斜杠:\[。此外,反斜杠\本身在Objective-C字符串中具有特殊含义,因此必须使用第二个反斜杠对其进行转义,并按如下方式编写:@"\\["。或者,您可以使用escapedPatternForString方法为您执行此转义。

NSString *openTagPattern = [NSRegularExpression escapedPatternForString:@"["];
NSString *closeTagPattern = [NSRegularExpression escapedPatternForString:@"]"];

然后我们想要找到几个不同的字符,直到结束括号。声明"除x"之外的任何字符;由[^x]编码,因此除了结尾括号之外的任何字符都由[^\]]编码。该括号char再次被转义为字面处理,在Objective-C字符串中,您将编写@"[^\\]]"。因为我们想要找到一个或多个此类字符,所以我们添加了+

NSString *tagTextPattern = [NSString stringWithFormat:@"[^%@]+", closeTagPattern];

最后我们需要一个结束括号。最终的正则表达式依次结合了这3种模式:

NSString *pattern = [NSString stringWithFormat:@"%@%@%@",
    openTagPattern,
    tagTextPattern,
    closeTagPattern];

然后,您可以创建一个NSRegularExpression实例并调用enumerateMatchesInString或matchesInString来为您提供所有匹配项。每个匹配都是一个NSTextCheckingResult对象,它具有range属性,可以将属性添加到原始属性字符串中。

如果您知道标记文本仅限于字母,数字和下划线,tagTextPattern可以简化为\w+,即"一个或多个单词字符" ,或者如果我们想要允许空格,标签(\s),模式将是[\w\s]+,即"一个或多个单词或空白字符" (不要忘记妥善逃脱它们。)

常见的错误是尝试使用表达式\[.+\],即"打开括号","再多出一个字符"和"关闭括号"。这不会起作用,因为匹配算法是贪婪的(匹配越长越好),对于.+子部分,它实际上也会占用结束括号,以及标记之后的其他所有内容(]后面的文字),可能会将多个标记加入到一个巨大的单个标记中,或者可能无法与最后的]匹配。

答案 1 :(得分:1)

如Wiktor建议的那样搜索平衡括号怎么样?

这是另一种实现这一目标的模式:

(\[(?>[^\[\]]+|(?1))*\])

Demo

我无法测试这种端到端,但应该可以使用NSRegularExpression