【问题标题】:How to represent Unicode characters in an ASCII regex pattern?如何以 ASCII 正则表达式模式表示 Unicode 字符?
【发布时间】:2011-06-12 19:45:11
【问题描述】:

RegEx 风格:C++ 中的wxRegEx

我需要匹配的字符串之一包含像 '...' (U+2026, Horizo​​ntal Ellipsis) 这样的字符,当粘贴到 Emacs 和'»'(U+00BB,右双角引号)在粘贴到 Emacs(ASCII 源代码模式)时保持 »

在正则表达式模式本身中,我尝试将 '...' 表示为 \205\\205 均无济于事。

解决这个问题的正确方法是什么?

更新:wxRegEx 文档指出,要表示 Unicode 字符,您使用 \uwxyz(其中 wxyz 正好是四个十六进制数字)Unicode 字符 U+ wxyz 在本地字节顺序中。

我试过了,但由于某种原因它对我不起作用(还)。

【问题讨论】:

  • 如果你使用 C++,我强烈推荐ICU regex library。您仍然可以按照我在回答中解释的方式使用符号名称。您可能也可以使用 PCRE,但我只使用 C 的 PCRE,而不是 C++。
  • @tchrist:再一次,您提供了非常有用的提示。谢谢!我肯定会长期遵循这个建议,但现在我需要使用内置的 wxRegEx 库。

标签: regex unicode escaping wxwidgets ascii


【解决方案1】:

这取决于语言。在许多语言中,不需要转义非 ASCII,但您可能必须告诉编译器源代码是什么编码。例如:

$ java -encoding UTF-8 SomeThing.java

$ perl -Mutf8 somescript

尽管使用 Perl、Python 和 Ruby 之类的东西,您可以将声明放在文件中,前提是它与 ASCII 向上兼容。例如:

#!/usr/bin/perl

use utf8;
use strict;
use warnings;
use autodie;

my $s = "Où se trouve mon élève?";

if ($s =~ /élève/) { ... }

# although of course this also works fine:

while ($s =~ /\b(\w+)\b/g) {
     print "Found <$1>\n";  
}

这是最简单的方法,我强烈推荐它:只需将真正的 UTF-8 字符放入源代码中即可。如果你必须想办法逃避事情,好吧,那就不方便了。

如果您打算使用转义符,那么您指定非 ASCII 符号的方式也会因语言而异。在 Java 中,您可以通过 \uXXXX 使用 asquerous Java 预处理器:

String s = "e\u0301le\u0300ve";

虽然我不推荐这种方式。如果要在模式中使用,可以延迟插值,这样既干净又杂乱:

String s = "e\\u0301le\\u0300ve";

第二种机制使您免于在 Java 预处理器使用它之后试图弄清楚它是什么(您不能使用\u0022,但可以使用\\0022),但是它会搞砸您的模式.CANON_EQ 标志。

大多数其他语言都有一种比 Java 更直接的方法——Java 也坚持使用丑陋的 UTF-16,除非您使用 java -encoding UTF-8 作为源代码。硬编码 UTF-16 代理绝对是愚蠢的。不要这样做!

在 Perl 中你可以使用:

my $s = "e\x{301}le\x{300}ve";  # NFD form
my $s = "\xE9l\xE8ve";          # NFC form

但你也可以象征性地命名它们

use charnames qw< :full >;
my $s_as_NFD = "e\N{COMBINING ACUTE ACCENT}le\N{COMBINING GRAVE ACCENT}e";
my $s_as_NFC = "\N{LATIN SMALL LETTER E WITH ACUTE}l\N{LATIN SMALL LETTER E WITH GRAVE}ve";

如果您愿意,可以缩短最后一个:

use charnames qw< :full latin >;
my $s_as_NFC = "\N{e WITH ACUTE}l\N{e WITH GRAVE}ve";

所有这些都比将幻数硬编码到您的代码中要好得多。

这一切都假设您的语言支持 Unicode,但很多不支持。

【讨论】:

  • 这是一个令人难以置信的答案,一旦我解决了恰好在 C++ 程序中的特定问题并且编译器抱怨源中存在非 ASCII 字符,我将接受它代码。因此,您也可以提供不太方便的方法。事实证明,wxRegEx 确实提供了一种表示 Unicode 字符 (\u2026) 的方法,但由于某种原因它(还)对我不起作用。我可能又错过了什么。
  • @Regex,用两个反斜杠试试"\\u2026"
  • 我也尝试了两个反斜杠。没有匹配。当我用“。”替换“\u2026”时有一场比赛(当然)。可能还有其他我想念的东西。我正在使用交互式控制台示例程序进行测试(以避免重新编译源代码)。
猜你喜欢
  • 1970-01-01
  • 2011-03-13
  • 1970-01-01
  • 1970-01-01
  • 2013-02-19
  • 1970-01-01
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
相关资源
最近更新 更多