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

标签 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 库有选项)。 但是,我不想使用 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 正则表达式中的等效项是:

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

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

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

我只想说 ECMA regex 和 Perl regex 之间的相似之处。什么不相似,但可以转换,我会尽量提一下。

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

按照 documentation for Perl regular expression :
  • 修饰符:
  • 只有 i , g , m在 ECMA 标准中,它们的行为与在 Perl 中相同。
  • s可以通过使用 2 个补充字符类在 ECMA 正则表达式中模拟点全修饰符,例如[\S\s] , [\D\d]
  • 不支持 xp旗帜。
  • 不知道有没有办法模拟其余的(前缀和后缀修饰符)。
  • 元字符:
  • 我对使用 \ 有点怀疑具有不解析为任何特殊含义的非元字符,但是如果您不从不需要的地方逃生应该没问题。 .在 ECMA 中排除了更多字符。其余的在 ECMA 正则表达式中的行为相同(即使 m 标志对 ^$ 的影响)。
  • 量词:
  • Greedy 和 Lazy 行为应该是一样的。 ECMA 正则表达式中没有占有行为。
  • 转义序列:
  • 没有 \a\e在 ECMA 正则表达式中。 \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可以通过手动转义引用的部分来模拟。
  • Perl 正则表达式中的八进制转义(少于 3 个八进制数字)可能会令人困惑。仔细检查上下文,阅读文档和/或测试正则表达式以确保您了解它在上下文中的作用,因为它可能是转义序列或反向引用。
  • 字符类和其他特殊转义:
  • \w , \W , \s , \S , \d , \D如果假设为 US-ASCII,则在 ECMA 正则表达式和 Perl 正则表达式中是等效的。如果涉及到 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 正则表达式涵盖了最常用的功能,因此正则表达式很可能是可转换的。

    引用 :

    ECMA RegExp Reference on MDN

    关于c++ - 将 Perl 正则表达式转换为等效的 ECMAScript 正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12127463/

    相关文章:

    c - 使用 CreateProcess,无法获取 CREATE_NO_WINDOW 来抑制控制台

    c++ - 具有不同长度的两个 vector 数组的线性插值

    bash shell脚本中的C++, super 初学者关于调用函数和调试的问题

    c++ - 如何从中心调整 QWidget 的大小

    regex - Powershell - 函数匹配 - 返回时获得额外的真/假

    ruby - 正则表达式但忽略某些单词

    java - 获取两个字符之间的子字符串

    C++ 简单字符检查

    c - Windows CE 上的 libcurl - curl_easy_perform(...) 不返回

    java - 如何在 Windows 10 上使用 Java 判断 wifi 或蜂窝连接