unicode - 如何检测非规范化的 unicode 字符?

标签 unicode utf-8 rust normalization unicode-normalization

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

我该怎么做?

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

最佳答案

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

嗯,这取决于“规范化”的定义。

例如:

/*!
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 - 如何检测非规范化的 unicode 字符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31904220/

相关文章:

php - 以十六进制和反向编码/解码字符串

python - BeautifulSoup webscraper 中的 UnicodeEncodeError

unicode - 在 C# 的控制台窗口中输出 Unicode 字符

java - 使用OutputStreamWriter和 "UTF-8"参数的Js/Java写入文件会产生ANSI编码文件

Java BASE64 utf8 字符串解码

rust - 在 Rust 中使用工厂模式时指定生命周期

Python: latex 符号到unicode?

c# - 如何使用 UTF-8 以外的代码页在 C# 中写出文本文件?

rust - 你如何处理 "could not parse code block as Rust code"rustdoc 警告?

rust - 无法打开创世配置文件