现在,我使用的是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中使用等效的正则表达式,而无需使用第三方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");
在上面的示例中,我要执行的操作是将
e
和format
转换为ECMAScript
样式表达式。是否可以找到将所有Perl正则表达式转换为
ECMAScript
样式的通用方法?有一些工具可以做到这一点吗?
任何帮助将不胜感激!
最佳答案
对于要转换的特定正则表达式,ECMA正则表达式中的等效项为:
/^(\d{3,4})[- ]?(\d{4})[- ]?(\d{4})[- ]?(\d{4})$/
在这种情况下,
\A
(在Perl regex中)与^
(在ECMA regex中)(匹配字符串的开头)具有相同的含义,\Z
(在Perl regex中)与$
(在ECMA regex中)相同的含义(匹配结尾)的字符串)。请注意,如果启用了多行模式,则ECMA regex中^
和$
的含义将更改为与行的开头和结尾匹配。ECMA regex是Perl regex的子集,因此,如果该regex使用Perl regex中的专有功能,则可能无法转换为ECMA regex。即使对于相同的语法,该语法在正则表达式的两个方言之间可能意味着稍有不同,因此检查文档并比较用法总是明智的。
我只想说说ECMA regex和Perl regex有何相似之处。什么不相似,但可转换,我将尽我所能提起。
ECMA正则表达式缺少与Unicode一起使用的功能,这些功能迫使您查找代码点并将其指定为字符类。
按照documentation for Perl regular expression去:
i
,g
和m
,它们的行为与Perl中的相同。 s
点全修饰符可以在ECMA正则表达式中通过使用2个补码字符类来模拟,例如[\S\s]
,[\D\d]
x
和p
标志。 \
并不能解决任何特殊含义的问题,我有些疑问,但是如果您不逃避不需要的地方就可以了。 ECMA中的.
排除了另外几个字符。其余的在ECMA正则表达式中表现相同(甚至m
标志对^
和$
的影响)。 \a
和\e
。 \t
,\n
,\r
和\f
相同。 \cX
-有所不同。 \xhh
在ECMA regex和Perl regex中很常见(指定2个十六进制数字是最安全的-否则,您将必须查阅文档以查看该语言如何处理少于2个十六进制数字的情况)。 \uhhhh
是ECMA正则表达式专有功能,用于指定Unicode字符。 Perl还有其他专有的方式来指定字符,例如\x{}
,\N{}
,\o{}
和\000
。 \l
,\u
,\L
和\U
是Perl正则表达式专用的。 \Q
和\E
。 假设我们使用US-ASCII,则ECMA regex和Perl regex中的
\w
,\W
,\s
,\S
,\d
,\D
是等效的。如果涉及Unicode,事情将变得一团糟。 \w
,\s
,\d
或在角色类中指定自己。 []
和已经提到的转义序列除外)。 \b
和\B
在这两种语言中是等效的,关于如何基于\w
进行定义。 ()
和反向引用是相同的。替换字符串中用于回溯对匹配文本的$n
是相同的。本节中的其余部分是Perl独有的功能。 s
标志是始终可以在ECMA regex中转换为等效表达式的标志)。 (?:pattern)
(非捕获组),(?=pattern)
(正向看),(?!pattern)
(负向看)是常见的。 (?#text)
。 结论:
如果regex充分利用了Perl regex的全部功能,或者在Boost库支持的级别上(例如递归regex),则无法将regex转换为ECMA regex。幸运的是,ECMA正则表达式涵盖了最常用的功能,因此正则表达式很可能是可转换的。
引用:
ECMA RegExp Reference on MDN