将Perl正则expression式转换为等价的ECMAScript正则expression式

现在我正在使用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库。

Perl中有很多正则expression式,所以我想把现有的Perl正则expression式转换成ECMAScript (或者VC ++ 2010支持的任何一种)。 转换后,我可以直接在VC ++ 2010中使用等效的正则expression式,而不使用第三方的libray。

一个例子:

 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风格的expression式。

有没有可能find一种将所有Perl正则expression式转换为ECMAScript风格的一般方法? 有没有一些工具可以做到这一点?

任何帮助将不胜感激!

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

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

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

ECMA正则表达式是Perl正则表达式的一个子集,所以如果正则表达式在Perl正则表达式中使用独有的功能,它很可能不能转换成ECMA正则表达式。 即使是相同的语法,语法也许意味着2种正则表达式之间的差别,所以检查文档和比较使用总是明智的。

我只是想说ECMA正则表达式和Perl正则表达式之间的相似之处。 什么是不相似的,但敞篷车,我会提到我的最大能力。

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

根据Perl正则表达式的文档 :

  • 修饰符:
    • 只有igm在ECMA标准中,并且与Perl中的行为相同。
    • 可以在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正则表达式中的八进制转义(其具有少于三个八进制数字)可能会令人困惑。 仔细检查上下文,阅读文档,和/或测试正则表达式,以确保你了解它在上下文中做什么,因为它可能是逃逸序列或反向引用。
  • 字符类和其他特殊的逃脱:
    • \w\W\s\S\d\D在ECMA正则表达式和Perl正则表达式中是等价的,如果使用US-ASCII。 如果涉及Unicode,事情将是一个混乱的血腥。
    • ECMA正则表达式中没有POSIX字符类。 使用上面的\w\s\d或者在字符类中指定自己。
    • 反向引用大部分是相同的 – 但我不知道它是否允许反向引用超过9 Perl和ECMA正则表达式。
    • 命名的参考可以通过反向参考进行模拟。
    • 其余的(除了[]和已经提到的转义序列)在ECMA正则表达式中不受支持。
  • 断言:
    • \b\B在两种语言中是相同的,关于如何根据\w定义它们。
  • 捕获组:分组()和后向引用是相同的。 在替换字符串中用来反向引用匹配文本的$n是相同的。 其余部分是Perl独有的功能。
  • 引用元字符:(内容已经在前面的章节中提到过)。
  • 扩展模式:
    • ECMA正则表达式不支持修改正则表达式中的标志。 根据标志是什么,你可能能够重写正则表达式( s标志是一个总是可以转换成ECMA正则表达式的等价表达式)。
    • Perl和ECMA之间只有(?:pattern) (非捕获组), (?=pattern) (正面向前看), (?!pattern) (负面向前看)是常见的。
    • 在ECMA正则表达式中没有评论,所以(?#text)可以被忽略。
    • ECMA正则表达式不支持后备。 Perl支持固定宽度的后视。 在某些情况下,使用Perl编写的积极正面的正则表达式可以转换为ECMA正则表达式,通过使得后台成为一个捕获组。
    • 如前所述,命名模式可以被转换为正常的捕获组,并且可以用编号的后向引用来引用。
    • 其余的是Perl独有的功能。
  • 特殊的回溯控制动词:这是Perl专有的,我不知道它们做了什么(以前从未碰过),更不用说转换了。 这很可能是他们不可兑换的情况。

结论

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

参考

ECM RegExp参考MDN