【问题标题】:<regex> having trouble with Cyrillic characters<regex> 遇到西里尔字符问题
【发布时间】:2020-06-15 13:16:19
【问题描述】:

我正在尝试使用标准的 &lt;regex&gt; 库来匹配一些西里尔字母:

  // This is a UTF-8 file.
  std::locale::global(std::locale("en_US.UTF-8"));

  string s {"Каждый охотник желает знать где сидит фазан."};
  regex re {"[А-Яа-яЁё]+"};

  for (sregex_iterator it {s.begin(), s.end(), re}, end {}; it != end; it++) {
    cout << it->str() << "#";
  }

但是,这似乎行不通。上面的代码结果如下:

  Кажд�#й#о�#о�#ник#желае�#зна�#�#где#�#иди�#�#азан#

而不是预期:

  Каждый#охотник#желает#знать#где#сидит#фазан

上面“�”符号的代码是\321

我检查了与grep 一起使用的正则表达式,它按预期工作。我的语言环境是en_US.UTF-8。 GCC 和 Clang 都产生相同的结果。

我有什么遗漏吗?有没有办法“驯服”&lt;regex&gt;,使其适用于西里尔字符?

【问题讨论】:

  • 我不太确定,但你不应该使用std::wstringstd::u32stringstd::wregexboost::u32regex等等吗?
  • 你的字符串是 utf-8 编码的吗?
  • @JohnDing 你说的完全正确。使用wstring 等人成功了。如果您不介意,我将使用这些知识很快回答我自己的问题。
  • @undercatapplaudsMonica 当然不是,继续。

标签: c++ regex locale regular-language cyrillic


【解决方案1】:

要使А-Я 等范围正常工作,您必须使用std::regex::collate

常量
...
collat​​e "[a-b]" 形式的字符范围将是区域敏感的。

将正则表达式改为

std::regex re{"[А-Яа-яЁё]+", std::regex::collate};

给出预期的结果。


根据源文件的编码,您可能需要在正则表达式字符串前面加上 u8

std::regex re{u8"[А-Яа-яЁё]+", std::regex::collate};

【讨论】:

  • 我可以确认这是可行的,并且与使用 wchars 相比,它似乎是一个不那么侵入性的解决方案,很惊讶regex::collate 在 Google 上的点击率如此之低!
【解决方案2】:

西里尔字母在 UTF-8 中表示为多字节序列。因此,处理该问题的一种方法是使用称为wstringstring 的“宽”版本。其他使用宽字符的函数和类型也需要替换为它们的“多字节意识”版本,通常通过在它们的名称前加上w 来完成。这有效:

std::locale::global(std::locale("en_US.UTF-8"));

wstring s {L"Каждый охотник желает знать где сидит фазан."};
wregex re {L"[А-Яа-яЁё]+"};

for (wsregex_iterator it {s.begin(), s.end(), re}, end {}; it != end; it++) {
  wcout << it->str() << "#";
}

输出:

Каждый#охотник#желает#знать#где#сидит#фазан#

(感谢@JohnDing 提出这个解决方案。)


另一种解决方案是使用regex::collate 使普通字符串对正则表达式区域设置敏感,有关详细信息,请参阅@OlafDietsche 的this answerThis topic 将阐明哪种解决方案在您的情况下可能更可取。 (在我的情况下,collate 是一个更好的主意!)

【讨论】:

猜你喜欢
  • 2015-05-19
  • 2010-11-02
  • 2020-08-14
  • 1970-01-01
  • 1970-01-01
  • 2019-07-23
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多