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

时间:2012-08-26 03:46:24

标签: c++ regex windows linux visual-studio-2010

现在我正在使用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 Library有选项)。 但是,我不想使用Boost Library。

有许多用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样式的一般方法? 是否有一些工具可以做到这一点?

任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:5)

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

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

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

ECMA正则表达式是Perl正则表达式的子集,因此如果正则表达式使用Perl正则表达式中的独占功能,则很可能它不能转换为ECMA正则表达式。即使是相同的语法,语法可能意味着正则表达式的两种方言之间略有不同,因此检查文档并比较使用情况总是明智的。

我只想说出ECMA正则表达式与Perl正则表达式之间的相似之处。什么不相似,但可兑换,我会尽我所能提到它。

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

根据documentation for Perl regular expression

  • 修饰符:
    • 只有igm符合ECMA标准,其行为与Perl相同。
    • s dot-all修饰符可以通过使用2个补充字符类在ECMA正则表达式中进行模拟,例如[\S\s][\D\d]
    • 无论如何都不支持xp旗帜。
    • 我不知道是否有模拟其余部分(前缀和后缀修饰符)。
  • 元字符:
    • 我对将\与非元字符使用并没有解决任何特殊含义有一点疑问,但如果你不逃避你不在的地方就应该没问题# 39; t需要。 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在ECMA正则表达式和Perl正则表达式中等效,如果假设为美国-ascii。如果涉及到Unicode,事情就会变得一团糟。
    • ECMA正则表达式中没有POSIX字符类。使用上述\w\s\d或在字符类中指定自己。
    • 后退参考大致相同 - 但我不知道它是否允许Perl和ECMA正则表达式的后引用超过9。
    • 可以使用后引用模拟命名引用。
    • ECMA正则表达式不支持其余的([]除外,已经提到的转义序列)。
  • 断言:
    • \b\B在两种语言中都是等效的,关于如何根据\w定义它们。
  • 捕获组:分组()和后退参考是相同的。 $n,在替换字符串中用于反向引用匹配的文本,是相同的。本节中的其余部分是Perl独有的功能。
  • 引用元字符:(已在前几节中提到的内容)。
  • 扩展模式:
    • ECMA正则表达式不支持修改regex中的标志。根据标志的不同,您可以重写正则表达式(s标志是一个可以在ECMA正则表达式中始终转换为等效表达式的标志。)
    • Perl和ECMA之间只有(?:pattern)(非捕获组),(?=pattern)(正向前看),(?!pattern)(负向前看)。
    • ECMA正则表达式中没有评论,因此可以忽略(?#text)
    • ECMA正则表达式不支持后视。 Perl支持固定宽度的后视。在某些情况下,使用Perl编写的具有正面外观的正则表达式可以转换为ECMA正则表达式,方法是将后视镜作为捕获组。
    • 如前所述,命名模式可以转换为普通捕获组,可以使用带编号的后引用来引用。
    • 其余是Perl的独家功能。
  • 特殊回溯控制动词:这是Perl独有的,我不知道它们做了什么(以前从未接触过它们),更不用说转换了。最有可能的情况是它们无法转换。

<强>结论

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

<强>参考

ECMA RegExp Reference on MDN