将Perl正则表达式转换为等效的ECMAScript正则表达式

5

我现在正在使用VC++ 2010,但是VC++ 2010的syntax_option_type只包含以下选项:

static const flag_type icase = regex_constants::icase;
static const flag_type nosubs = regex_constants::nosubs;
static const flag_type optimize = regex_constants::optimize;
static const flag_type collate = regex_constants::collate;
static const flag_type ECMAScript = regex_constants::ECMAScript;
static const flag_type basic = regex_constants::basic;
static const flag_type extended = regex_constants::extended;
static const flag_type awk = regex_constants::awk;
static const flag_type grep = regex_constants::grep;
static const flag_type egrep = regex_constants::egrep;

它不包含perl_syntax_group(Boost库有此选项)。 然而,我不想使用Boost库。

有许多用Perl编写的正则表达式,所以我想将现有的Perl正则表达式转换为ECMAScript(或VC++ 2010支持的任何一种)。 转换后,我可以直接在VC++ 2010中使用等效的正则表达式,而无需使用第三方库。

一个例子:

const boost::tregex e(__T("\\A(\\d{3,4})[- ]?(\\d{4})[- ]?(\\d{4})[- ]?(\\d{4})\\z"));
const CString human_format = __T("$1-$2-$3-$4");
CString human_readable_card_number(const CString& s)
{
   return boost::regex_replace(s, e, human_format);
}
CString credit_card_number = "1234567887654321";
credit_card_number = human_readable_card_number(credit_card_number);
assert(credit_card_number == "1234-5678-8765-4321");

在上面的例子中,我想做的是将eformat转换为ECMAScript风格的表达式。
是否有一种通用方法来将所有Perl正则表达式转换为ECMAScript风格?是否有一些工具可以实现这一点?
任何帮助都将不胜感激!

ECMA Script正则表达式是Perl正则表达式的子集。因此,如果您使用Perl正则表达式独有的功能,则无法进行转换。 - nhahtdh
谢谢您的回复。如果我不使用Perl正则表达式的专有功能,是否有一种通用的方法来进行转换? - user1475359
1个回答

5

对于您想转换的特定正则表达式,在ECMA正则表达式中的等价物是:

/^(\d{3,4})[- ]?(\d{4})[- ]?(\d{4})[- ]?(\d{4})$/

在这种情况下,Perl正则表达式中的\A与ECMA正则表达式中的^(匹配字符串开始)具有相同的含义,而Perl正则表达式中的\Z与ECMA正则表达式中的$(匹配字符串结束)具有相同的含义。请注意,如果启用多行模式,则ECMA正则表达式中^$的含义将变为匹配行的开头和结尾。

ECMA正则表达式是Perl正则表达式的一个子集,因此,如果正则表达式使用Perl正则表达式中的独占功能,则很可能无法转换为ECMA正则表达式。即使对于相同的语法,在两个正则表达式方言之间,语法的含义也可能略有不同,因此,始终明智的做法是查阅文档并比较用法。

我只会说ECMA正则表达式和Perl正则表达式之间的相似之处。不相似但可转换的部分,我会尽我所能提到它们。

ECMA正则表达式缺乏处理Unicode的功能,这迫使您查找代码点并将其指定为字符类。

按照Perl正则表达式文件的文档进行操作:

  • 修饰符:
    • 只有 i, g, m 在 ECMA 标准中,且它们的行为与 Perl 相同。
    • s 点号匹配所有修饰符在 ECMA 正则表达式中可以通过使用 2 个补码字符类来模拟,例如 [\S\s][\D\d]
    • 没有任何方式支持 xp 标志。
    • 我不知道是否有任何方法来模拟其余的前缀和后缀修饰符。
  • 元字符:
    • 我对在非元字符中使用 \ 有些怀疑,如果您不需要转义,则应该没问题。ECMA 中的 . 排除了更多的字符。其余在 ECMA 正则表达式中的行为相同(甚至是 m 标志对 ^$ 的影响)。
  • 量词:
    • 贪婪和懒惰行为应该相同。在 ECMA 正则表达式中没有占有性行为。
  • 转义序列:
    • 在 ECMA 正则表达式中没有 \a\e\t\n\r\f 相同。
    • 如果正则表达式有 \cX,请检查文档-存在差异。
    • \xhh 在 ECMA 正则表达式和 Perl 正则表达式中都很常见(指定 2 个十六进制数字是最安全的 - 否则,您将不得不查阅文档,以了解语言如何处理少于 2 个十六进制数字的情况)。
    • \uhhhh 是 ECMA 正则表达式的 独占功能,用于指定 Unicode 字符。Perl 有其他 独占 指定字符的方式,例如 \x{}\N{}\o{}\000
    • \l\u\L\U 是 Perl 正则表达式的 独占
    • \Q\E 可以通过手动转义引用部分来模拟。
    • 在 Perl 正则表达式中,八进制转义(小于 3 个八进制数字)可能会令人困惑。仔细检查上下文,阅读文档和/或测试正则表达式,以确保您理解它在上下文中的作用,因为它可能是转义序列或反向引用。
  • 字符类和其他特殊转义:
    • \w\W\s\S\d\D 在假定 US-ASCII 的情况下,在 ECMA 正则表达式和 Perl 正则表达式中是等价的。如果涉及到 Unicode,则情况将变得一团糟。
    • ECMA 正则表达式中没有 POSIX 字

      结论:

      如果正则表达式使用了 Perl 正则表达式的全部功能,或者使用 Boost 库支持的级别(例如递归正则表达式),那么将正则表达式转换为 ECMA 正则表达式是不可能的。幸运的是,ECMA 正则表达式涵盖了最常用的功能,因此很可能可以将正则表达式转换。

      参考:

      MDN上的ECMA RegExp参考


感谢您的回复。这是正确等效的ECMAScript正则表达式。 是否有一种通用的方法可以将所有Perl正则表达式转换为ECMAScript样式? - user1475359
1
@Falconapollo:全部:不是。常见的:大多数是。 - nhahtdh
这不是我的错。我不知道谁给你的回答点了踩。我认为你的回答很完美。 - user1475359
@Falconapollo:不管他/她是谁,反对票最终都会被移除的。(我知道你没有投反对票,因为你接受了答案)。 - nhahtdh
你好,可以告诉我你的MSN或其他即时通讯账号吗?这样我们可以更方便地使用即时通讯软件进行交流。 - user1475359

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接