【问题标题】:using regular expression with unicode string in C在C中使用带有unicode字符串的正则表达式
【发布时间】:2017-04-26 22:06:04
【问题描述】:

我目前在 unicode 字符串上使用正则表达式,但我只需要匹配 ASCII 字符,因此有效地忽略所有 unicode 字符,直到现在 regex.h 中的函数工作正常(我在 linux 上,所以编码是 utf8)。但是有人可以确认这样做是否真的可以吗?还是我需要一个 Unicode 上的正则表达式库(比如 ICU?)

【问题讨论】:

  • UTF-8 对非 ASCII 字符进行编码,使它们从不匹配 ASCII 字符,因此如果您搜索或匹配的只是这些字符,那么它应该是安全的.当然,既然我这么说了,就会有人过来告诉我我错了——我欢迎反例。

标签: c regex unicode utf-8


【解决方案1】:

你需要小心你的模式和你要匹配的文本。

举个例子,给定表达式a.b

"axb" matches 
"aèb" does NOT match

原因是 è 在 UTF-8 编码时是两个字节长,但 . 只会匹配第一个。

只要你只匹配 sequences 的 ASCII 字符,你就安全了。如果你混合使用 ASCII 和非 ASCII 字符,你就有麻烦了。

您可以尝试将单个 UTF-8 编码的“字符”与以下内容匹配:

([\xC0-\xDF].|[\xE0-\xEF]..|\xF0...|.)

但这假设文本编码正确(坦率地说,我从未尝试过)。

【讨论】:

    【解决方案2】:

    UTF-8 is a variable length encoding;有些字符是 1 个字节,有些是 2 个,有些是 3 或 4 个。您现在知道每个字符的前缀要读取的字节数。 0 表示 1 字节,110 表示 2 字节,1110 表示 3 字节,11110 表示 4 字节。

    如果您尝试将 UTF-8 字符串读取为 ASCII 或任何其他固定宽度的编码,事情将变得非常错误......除非 UTF-8 字符串只包含 1 字节字符,在这种情况下它匹配 ASCII .

    然而因为 UTF-8 中没有字节包含空字节,并且没有任何额外的字节可以与 ASCII 混淆,如果你真的只匹配 ASCII ,您可能能够逃脱它......但我不推荐它,因为有比 POSIX 更好的正则表达式选项,它们易于使用,以及为什么要留下隐藏编码在你的代码中炸弹以便稍后处理一些傻瓜? (注意:那个傻逼可能是你)

    相反,请使用 Unicode 感知正则表达式库,例如 Perl 兼容正则表达式 (PCRE)。 PCRE is Unicode aware 通过将 PCRE2_UTF 标志传递给 pcre2_compile。 PCRE 正则表达式语法比 POSIX 正则表达式更强大,更被广泛理解,而且 PCRE 具有更多的功能。而PCRE comes with Gnome Lib 本身就提供了非常方便的 C 函数的盛宴。

    【讨论】:

    • 我只是 unicode 的新手。如果可能的话,我只是不喜欢使用外部库,这就是为什么我想知道我是否能找到一种方法。无论如何,我会尝试 PCRE,谢谢你的建议。
    • @AtheS21 标准 C 没有太多的 Unicode 支持。它对很多事情没有太多影响。与其一一提取,我建议您查看 Gnome Lib 或其他提供所有缺失部分的第三方库。
    猜你喜欢
    • 2015-03-30
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2011-02-19
    • 2011-04-06
    相关资源
    最近更新 更多