【问题标题】:How to detect unicode characters that are non-normalized?如何检测非规范化的 unicode 字符?
【发布时间】:2015-11-01 11:05:30
【问题描述】:

给定一个 UTF-8 字符串 (&str),我想找出任何未规范化的字符范围(例如 a\u{300} 而不是 \u{e0})。

我该怎么做?

编辑:感谢 DK 纠正了我错误的 UTF-8 序列。组合字符出现在之后a,而不是之前。

【问题讨论】:

    标签: unicode utf-8 rust normalization unicode-normalization


    【解决方案1】:

    编辑:我刚刚意识到我得到的结果的原因是你的示例字符串是向后的。组合代码点应该排在第二位,而不是第一位。我已经相应地更新了答案。

    嗯,这取决于“标准化”的定义。

    例如:

    /*!
    Add this to a `Cargo.toml` manifest:
    
    ```cargo
    [dependencies]
    unicode-normalization = "0.1.1"
    ```
    */
    extern crate unicode_normalization;
    
    fn main() {
        for test_str in vec!["a\u{300}", "\u{e0}"] {
            is_nfd(test_str);
            is_nfkd(test_str);
            is_nfc(test_str);
            is_nfkc(test_str);
        }
    }
    
    macro_rules! norm_test {
        ($fn_name:ident, $norm_name:ident) => {
            fn $fn_name(s: &str) {
                use unicode_normalization::UnicodeNormalization;
                println!("is_{}({:?}):", stringify!($norm_name), s);
                let is_norm = s.chars().zip(s.$norm_name())
                    .inspect(|&(a, b)| println!(" - ({:x}, {:x})", a as u32, b as u32))
                    .all(|(a, b)| a == b);
                println!(" is_norm: {}", is_norm);
            }
        };
    }
    
    norm_test! { is_nfd, nfd }
    norm_test! { is_nfkd, nfkd }
    norm_test! { is_nfc, nfc }
    norm_test! { is_nfkc, nfkc }
    

    这会产生以下输出:

    is_nfd("a\u{300}"):
     - (61, 61)
     - (300, 300)
     is_norm: true
    is_nfkd("a\u{300}"):
     - (61, 61)
     - (300, 300)
     is_norm: true
    is_nfc("a\u{300}"):
     - (61, e0)
     is_norm: false
    is_nfkc("a\u{300}"):
     - (61, e0)
     is_norm: false
    is_nfd("\u{e0}"):
     - (e0, 61)
     is_norm: false
    is_nfkd("\u{e0}"):
     - (e0, 61)
     is_norm: false
    is_nfc("\u{e0}"):
     - (e0, e0)
     is_norm: true
    is_nfkc("\u{e0}"):
     - (e0, e0)
     is_norm: true
    

    所以"a\u{300}" 是 NFD 和 NFKD,而 "\u{e0}" 是 NFC 和 NFKC。我不知道 K 和非 K 变体之间有什么不同的示例,尽管 Unicode FAQ on Normalization 可能会比我能更好地解释事情。

    【讨论】:

    • 因此,如果我想检测字符串中的非规范化范围,我需要首先找到只有第一个字符的 unicode_combining_class 为零的字符范围,并检查它们是否正常(取决于定义,正如你所概述的)。
    • @DK:您可以在unicode.org/reports/tr15 中看到 K 表格的示例(例如图 6)。从本质上讲,NFD 和 NFC 是规范等价物,而它们的 K 对应物是关于较弱的兼容性等价物,包括将下标/上标更改为常规字符(除其他外)。例如,25 在 NFD 或 NFC 中编码为 0032 2075(其中 2075 在上标位置为 5),但在 NFKD 或 NFKC 中为 0032 0035(其中 0035 是常规 5) .
    猜你喜欢
    • 2023-03-06
    • 2018-04-16
    • 2016-06-09
    • 2011-12-10
    • 2011-06-20
    • 2012-02-07
    • 2013-05-04
    • 1970-01-01
    相关资源
    最近更新 更多