如何在 Swift NSRegularExpression 中捕获单词边界?

How to capture a word boundary in Swift NSRegularExpression?

我想捕获以某个前缀开头的字符串中的所有 单词 。例如所有以 t

开头的单词
if let regex = try? NSRegularExpression(pattern: #"t[^ ]+"#, options: NSRegularExpression.Options.caseInsensitive) {
    let input = "this is the best test"
    let matches = regex.matches(in: input, options: [], range: NSRange(location: 0, length: input.count))
        
    for match in matches {
        print((input as NSString).substring(with: match.range))
    }
}

在上面的代码中,我使用了一个简单的 space 作为分隔符 (#"t[^ ]+"#) 并且输出符合预期:

this
the
test

但是,不仅要考虑 spaces,还要考虑所有的单词边界。因此,我将 space 替换为 \b 以匹配所有边界 (#"t[^\b]+"#)。但是,这不起作用:

this is the 
t test

看来这段代码并没有寻找单词边界,而是简单地寻找b...这是为什么?

我认为在正则表达式前后使用 # 会创建一个原始字符串,从而将 \ 正确地传送到正则表达式系统。所以 #"t[^\b]+"# 应该和 "t[^\b]+" 一样并被翻译成 t[^\b]+,不是吗?

或者单词边界运算符 \b 在 Swift 正则表达式中不可用?

编辑:

根据 ICU Documentation \b 匹配 词边界 ,因此 [^\b](除词边界外的任何内容)不应该是与 [^b] 相同(除了 a b 之外的任何东西),应该吗?

不过\b好像不能套用吧?但是 \B 应该做同样的事情(除了单词边界之外的任何东西)。

所以我尝试使用 #"t\B+"# 代替。但是,这根本找不到任何匹配项。

问题仍然存在:如何在Swift NSRegularExpression中匹配单词边界?

#"t[^\b]+"# 字符串字面量导致 t[^\b]+ 正则表达式,它只匹配 t 然后一个或多个字符而不是 b 字符([^\b] 在 ICU 正则表达式中等于 [^b]

要匹配 t 然后一个或多个单词字符(即,直到下一个最左边的单词边界),您可以使用

pattern: #"t\w+"#

其中 \w+ 将匹配一个或多个单词字符。

一个[...]是一个字符set/class。字符 class 意味着匹配 个字符 \b是一个词边界只在一个字符class之外,因为词边界不是一个字符,它是匹配字符串中某个 位置 的零宽度断言。所有零宽度断言在字符 class 中都失去了它们特殊的“零宽度”含义。 [.$] 并不表示 . 或字符串结尾,它匹配 .$ 字符。 [.\z] 不匹配 . 或字符串的末尾,它匹配 .z 因为 \ 被省略,因为 \z 不是有效的转义序列。

此外,t\B+ 没有什么意义,因为 \B,还有一个 零宽度断言 ,匹配一个 位置 在不是单词边界位置的字符串中。请注意,零宽度断言不会 consume 文本,即没有文本添加到整体匹配内存缓冲区,并且正则表达式索引保持在尝试零宽度断言模式之前的位置。通过在 \B 之后添加 +,您只需告诉正则表达式引擎匹配 t 之后的 location 这不是单词边界,因此正则表达式引擎匹配 t\B+ 的方式与它是 t\B 的方式相同,即它只匹配后跟单词 char(字母、数字、连接符)的 t

\w 匹配(并且 消耗 )单词字符,因此如果您需要匹配(并真正得到结果)t 之后的任何字符直到第一个单词边界,你只需要使用这个 \w 模式,t\w*t\w+ (如果 t 之后必须至少有一个单词字符)。