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

5 c++ regex linux windows visual-studio-2010

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

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;
Run Code Online (Sandbox Code Playgroud)

它不包含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");
Run Code Online (Sandbox Code Playgroud)

在上面的例子中,我想要做的是转换eformatECMAScript风格的表达.

是否有可能找到将所有Perl正则表达式转换为ECMAScript样式的一般方法?有一些工具可以做到这一点吗?

任何帮助将不胜感激!

nha*_*tdh 5

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

/^(\d{3,4})[- ]?(\d{4})[- ]?(\d{4})[- ]?(\d{4})$/
Run Code Online (Sandbox Code Playgroud)

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

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

我只想说一下ECMA正则表达式和Perl正则表达式之间有什么相似之处.什么不相似,但可兑换,我会尽我所能提到它.

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

根据Perl正则表达式文档:

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

结论:

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

参考:

MDMA上的ECMA RegExp参考