这个问题是 Do C++11 regular expressions work with UTF-8 strings? 的延伸
#include <regex>
if (std::regex_match ("中", std::regex("中") )) // "\u4e2d" also works
std::cout << "matched\n";
该程序是在 Mac Mountain Lion 上使用 clang++
编译的,具有以下选项:
clang++ -std=c++0x -stdlib=libc++
上面的代码有效。这是一个标准范围正则表达式 "[一-龠々〆ヵヶ]"
用于匹配任何日文汉字或中文字符。它适用于 Javascript 和 Ruby,但我似乎无法在 C++11 中使用范围,即使使用类似的版本 [\u4E00-\u9fa0]
。下面的代码与字符串不匹配。
if (std::regex_match ("中", std::regex("[一-龠々〆ヵヶ]")))
std::cout << "range matched\n";
更改语言环境也无济于事。有什么想法吗?
编辑
所以我发现,如果您在末尾添加 +
,所有范围都有效。在这种情况下[一-龠々〆ヵヶ]+
,但是如果你添加{1}
[一-龠々〆ヵヶ]{1}
它不起作用。此外,它似乎超出了它的界限。它不会匹配拉丁字符,但会匹配 は
即 \u306f
和 ぁ
即 \u3041
。它们都位于 \u4E00
nhahtdh 还建议 regex_search 也可以在不添加 +
的情况下工作,但通过将值拉到其范围之外,它仍然会遇到与上述相同的问题。也玩了一些语言环境。 Mark Ransom 建议它将 UTF-8 字符串视为一组愚蠢的字节,我认为这可能就是它正在做的事情。
进一步插入 UTF-8 变得困惑的理论,[a-z]{1}
和 [a-z]+
匹配 a
,但只有 [一-龠々〆ヵヶ]+
匹配任何字符,而不是 [一-龠々〆ヵヶ]{1}
。
最佳答案
UTF-8编码,字符串"[一-龠々〆ヵヶ]"
等于这个:"[\xe4\xb8\x80-\xe9\xbe\xa0\xe3\x80\x85\xe3\x80\x86\xe3\x83\xb5\xe3\x83\xb6]"
。这不是您要查找的 droid 字符类。
您要查找的字符类包括:
- U+4E00..U+9FA0 范围内的任意字符;或
- 任何字符々、〆、ヵ、ヶ。
您指定的字符类包括:
- 任何“字符”\xe4 或\xb8;或
- \x80..\xe9 范围内的任何“字符”;或
- 任何“字符”\xbe、\xa0、\xe3、\x80、\x85、\xe3(再次)、\x80(再次)、\x86、\xe3(再次)、\x83、\xb5 、\xe3(再次)、\x83(再次)、\xb6。
是不是很乱?看到问题了吗?
这将不匹配“拉丁”字符(我假设您的意思是 a-z 之类的),因为在 UTF-8 中,它们都使用低于 0x80 的单个字节,并且这些字符都不属于那个杂乱的字符类。
它也不会匹配 "中"
因为 "中"
有三个“字符”,而您的正则表达式只匹配那个奇怪的长列表中的一个“字符” .试试 assert(std::regex_match("中", std::regex("...")))
你会看到。
如果你添加一个 +
它会起作用,因为 "中"
在你奇怪的长列表中有三个“字符”,现在你的正则表达式匹配一个或多个。
如果您改为添加 {1}
,则它不匹配,因为我们又将三个“字符”与一个匹配。
顺便说一下 "中"
匹配 "中"
因为我们将三个“字符”与相同的三个“字符”以相同的顺序匹配。
带有 +
的正则表达式实际上会匹配一些不需要的东西,因为它不关心顺序。可以从 UTF-8 中的字节列表生成的任何字符都将匹配。它将匹配 "\xe3\x81\x81"
(ぁ U+3041),它甚至会匹配无效的 UTF-8 输入,例如 "\xe3\xe3\xe3\xe3"
.
更大的问题是您使用的正则表达式库甚至没有对 Unicode 的 1 级支持,这是最低要求。它会处理字节数,而您宝贵的小型正则表达式对此无能为力。
更大的问题是您使用一组硬编码的字符来指定“任何日文汉字或汉字”。为什么不使用 Unicode Script 属性呢?
R"(\p{Script=Han})"
哦,对了,这不适用于 C++11 正则表达式。有那么一瞬间,我几乎忘记了那些 Unicode 比没用更烦人。
那你该怎么办?
您可以将输入解码为 std::u32string
并使用 char32_t
进行匹配。这不会给您带来麻烦,但是当您的意思是“一组共享某个属性的字符”时,您仍然会硬编码范围和异常。
我建议你忘记 C++11 正则表达式并使用一些具有最低 1 级 Unicode 支持的正则表达式库,如 ICU 中的那个。 .
关于c++ - C++11 正则表达式中的 UTF-8 字符范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15882991/