【问题标题】:Regular expression to select only the words surrounded by Special Characters正则表达式仅选择特殊字符包围的单词
【发布时间】:2018-03-12 05:20:15
【问题描述】:

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

这是一个包含 [示例词] 的 [示例] 字符串

我想更改上述字符串中[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];
    }
}

我也尝试使用正则表达式来获取特定特殊字符内的所有单词,但我无法制作这样的正则表达式。

【问题讨论】:

  • 使用NSScanner 可能会更容易。
  • 正则表达式可能是"\\w+(?=[^\\[\\]]*])"(如果括号总是平衡的)。
  • 这是另一个正则表达式 (\G(?!\A)\s+|\[)([^\s\]\[]+),您可以使用它,但您必须连接第 1 组和修改后的第 2 组。

标签: ios objective-c regex


【解决方案1】:

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

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

然后我们要找到几个不同的字符直到结束括号。语句“除 x 之外的任何字符”由[^x] 编码,因此除了结束括号之外的任何字符都由[^\]] 编码。该括号字符再次被转义以进行字面处理,并且在 Objective-C 字符串中您将编写@"[^\\]]"。因为我们要找到1个或多个这样的字符,所以我们添加+

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

最后我们需要一个右括号。最终的正则表达式只是按顺序组合了这 3 种模式:

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

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

如果您知道标签文本仅限于字母、数字和下划线,则 tagTextPattern 可以简化为 \w+,即“一个或多个单词字符”,或者如果我们想允许空格,制表符 (\s) 模式将是 [\w\s]+,即“一个或多个单词或空格字符”(不要忘记正确转义它们)。

一个常见的错误是尝试使用表达式\[.+\],即“开括号”、“再一个任意字符”和“右括号”。这是行不通的,因为匹配算法是贪婪的(匹配越长越好),并且对于 .+ 子部分,它实际上也会吃掉右括号,以及标签后面的所有其他内容(后面的文本]),并可能将多个标签连接成一个巨大的单个标签,或者可能无法匹配最后一个 ]

【讨论】:

    【解决方案2】:

    按照 Wiktor 的建议搜索平衡括号怎么样?

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

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

    Demo

    我无法进行端到端测试,但使用 NSRegularExpression 应该是可行的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多