繁体   English   中英

C ++ 11 Regex中的UTF-8字符范围

[英]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]" 这不是您正在寻找的 机器人 角色类。

您正在寻找的角色类包括:

  • U + 4E00..U + 9FA0范围内的任何字符; 要么
  • 任何字符々,〆,ヵ,ヶ。

您指定的字符类包括:

  • 任何“字符”\\ 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM