首页 > 解决方案 > 这个混合字符串如何在 unicode 单词边界上拆分

问题描述

考虑字符串"abc를"。根据unicode的分词demo实现,这个字符串应该被分成两个词,"abc""를"。然而,单词边界检测的 3 种不同的 Rust 实现(regex, unic-segment, unicode-segmentation都不同意,并将该字符串分组为一个单词。哪种行为是正确的?

作为后续,如果分组行为是正确的,那么以仍然主要尊重单词边界的方式扫描此字符串以查找搜索词“abc”的好方法是什么(为了检查字符串翻译的有效性) . 我想匹配类似的东西,"abc를"但不匹配类似的东西abcdef

标签: unicoderustsplitword-boundary

解决方案


我不太确定分词的演示是否应该被视为基本事实,即使它在官方网站上也是如此。例如,它认为"abc를"( "abc\uB97C") 是两个独立的词,但认为"abc를"( "abc\u1105\u1173\u11af") 是一个词,即使前者分解为后者。

单词边界的想法并不是一成不变的。Unicode 有一个字边界规范,它概述了应该和不应该出现断字的位置。但是,它有一个广泛的注释部分,用于详细说明其他案例(强调我的):

不可能提供一套统一的规则来解决跨语言的所有问题或处理给定语言中的所有模棱两可的情况。本附件中提出的规范的目标是提供一个可行的默认值;量身定制的实现可以更加复杂。

对于泰语、老挝语、高棉语、缅甸语和其他通常在单词之间不使用空格的脚本,一个好的实现不应该依赖于默认的单词边界规范。它应该使用更复杂的机制,这也是换行所必需的。日文和中文等表意文字更加复杂。如果韩文文本没有空格,则同样适用。然而,在没有更复杂的机制的情况下,本附件中规定的规则提供了一个明确定义的默认值。

...

我的理解是,您列出的板条箱遵循规范,没有进一步的上下文分析。为什么演示不同意我不能说,但它可能是尝试实现这些边缘情况之一。


为了解决您的具体问题,我建议使用Regexwith\b来匹配单词边界。不幸的是,这遵循相同的 unicode 规则,不会被认为"를"是一个新词。然而,这个正则表达式实现提供了一个回退到 ascii 行为的逃生舱口。只需用于(?-u:\b)匹配非 unicode 边界:

use regex::Regex;

fn main() {
    let pattern = Regex::new("(?-u:\\b)abc(?-u:\\b)").unwrap();
    println!("{:?}", pattern.find("some abcdef abc를 sentence"));
}

您可以在操场上自己运行它来测试您的案例,看看这是否适合您。


推荐阅读