[英]Range of UTF-8 Characters in C++11 Regex
这个问题是Do C ++ 11正则表达式与UTF-8字符串一起使用的扩展吗?
#include <regex>
if (std::regex_match ("中", std::regex("中") )) // "\u4e2d" also works
std::cout << "matched\n";
该程序使用clang++
在Mac Mountain Lion上clang++
具有以下选项:
clang++ -std=c++0x -stdlib=libc++
上面的代码有效。 这是一个标准范围正则表达式"[一-龠々〆ヵヶ]"
用于匹配任何日文汉字或汉字。 它适用于Javascript和Ruby,但我似乎无法在C ++ 11中使用范围,即使使用类似的版本[\一-\龠]
。 下面的代码与字符串不匹配。
if (std::regex_match ("中", std::regex("[一-龠々〆ヵヶ]")))
std::cout << "range matched\n";
改变语言环境也没有帮助。 有任何想法吗?
所以我发现如果你在末尾添加一个+
,所有范围都有效。 在这种情况下[一-龠々〆ヵヶ]+
,但如果添加{1}
[一-龠々〆ヵヶ]{1}
则不起作用。 而且,它似乎超越了它的界限。 它不匹配拉丁字符,但它将匹配は
,即\は
和ぁ
,即\ぁ
。 它们都位于\一
nhahtdh还提出了regex_search,它也可以在不添加+
情况下工作,但它仍然会遇到与上面相同的问题,因为它会超出其范围。 同时也使用了语言环境。 Mark Ransom建议它将UTF-8字符串视为一组愚蠢的字节,我认为这可能就是它所做的。
进一步推动UTF-8混淆的理论, [az]{1}
和[az]+
匹配a
,但只有[一-龠々〆ヵヶ]+
匹配任何一个字符,而不是[一-龠々〆ヵヶ]{1}
。
以UTF-8编码,字符串"[一-龠々〆ヵヶ]"
等于这一个: "[\\xe4\\xb8\\x80-\\xe9\\xbe\\xa0\\xe3\\x80\\x85\\xe3\\x80\\x86\\xe3\\x83\\xb5\\xe3\\x83\\xb6]"
。 这不是您正在寻找的
机器人
角色类。
您正在寻找的角色类包括:
您指定的字符类包括:
凌乱不是吗? 你看到了问题吗?
这与“拉丁”字符不匹配(我假设你的意思是像az这样的东西),因为在UTF-8中,所有字符都使用低于0x80的单个字节,而且这些字符都不在那个混乱的字符类中。
它不会匹配"中"
,因为"中"
有三个“字符”,而你的正则表达式只匹配那个奇怪的长列表中的一个“字符”。 尝试assert(std::regex_match("中", std::regex("...")))
,你会看到。
如果你添加+
它是有效的,因为"中"
在你奇怪的长列表"中"
有三个“字符”,现在你的正则表达式匹配一个或多个。
如果您改为添加{1}
它不匹配,因为我们回到匹配三个“字符”与一个。
顺便说一句, "中"
匹配"中"
因为我们将三个“字符”与相同顺序的相同三个“字符”匹配。
带+
的正则表达式实际上会匹配一些不需要的东西,因为它不关心顺序。 可以从UTF-8中的字节列表中生成的任何字符都匹配。 它将匹配"\\xe3\\x81\\x81"
(ぁU+ 3041),它甚至会匹配无效的UTF-8输入,如"\\xe3\\xe3\\xe3\\xe3"
。
更大的问题是你正在使用一个甚至没有1级支持Unicode的正则表达式库,这是最低要求。 它会消耗大量的字节,而且你的珍贵的小正则表达式对它没有多大帮助。
更大的问题是你使用一组硬编码的字符来指定“任何日文汉字或汉字”。 为什么不使用Unicode Script属性呢?
R"(\\p{Script=Han})"
哦,对,这不适用于C ++ 11正则表达式。 在那里,我几乎忘记了那些比使用Unicode无用的烦人。
那你该怎么办?
您可以将输入解码为std::u32string
并使用char32_t
进行匹配。 这不会给你这个烂摊子,但当你的意思是“一组共享某个属性的字符”时,你仍然会硬编码范围和异常。
我建议你忘记C ++ 11正则表达式并使用一些具有最低1级Unicode支持的正则表达式库,就像ICU中那样 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.