【问题标题】:Convert Perl regular expression to equivalent ECMAScript regular expression将 Perl 正则表达式转换为等效的 ECMAScript 正则表达式
【发布时间】:2012-08-21 02:01:09
【问题描述】:

现在我用的是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 脚本正则表达式是 Perl 正则表达式的子集。因此,如果您使用 Perl 正则表达式独有的功能,则无法转换。
  • 感谢您的回复。如果我不使用 Perl 正则表达式独有的功能,是否有可能找到一种通用的方法来进行转换?

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


【解决方案1】:

对于您要转换的特定正则表达式,ECMA 正则表达式中的等效项是:

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

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

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

我只会说 ECMA 正则表达式和 Perl 正则表达式之间的相似之处。什么不相似,但可以转换,我会尽可能地提到它。

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

按照documentation for Perl regular expression

  • 修饰符:
    • 只有 igm 在 ECMA 标准中,它们的行为与在 Perl 中相同。
    • s dot-all 修饰符可以在 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 正则表达式中的八进制转义(少于 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 支持固定宽度的look-behind。在某些情况下,可以将用 Perl 编写的具有正向查找的正则表达式转换为 ECMA 正则表达式,方法是使后向成为一个捕获组。
    • 如前所述,命名模式可以转换为正常的捕获组,并且可以通过编号的反向引用进行引用。
    • 其余的是 Perl 独有的功能。
  • 特殊回溯控制动词:这是 Perl 独有的,我不知道这些是做什么的(以前从未接触过它们),更不用说转换了。很可能它们无论如何都不能转换。

结论

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

参考

ECMA RegExp Reference on MDN

【讨论】:

  • 感谢您的回复。这是正确的等效 ECMAScript 正则表达式。是否有可能找到一种通用方法将所有 Perl 正则表达式转换为 ECMAScript 样式?
  • @Falconapollo:全部:没有。常见的:大部分是的。
  • 这不是我的错。我不知道谁投了反对票。我认为你的回答很完美。
  • @Falconapollo:无论他/她是谁,无论如何都会删除反对票。 (我知道你没有投反对票,因为你接受了答案)。
  • 嗨,我可以给我您的 MSN 或其他 IM 帐户吗?我们可以通过 IM 软件更方便地进行交流。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 2011-10-02
  • 2016-04-02
  • 1970-01-01
  • 2019-05-11
  • 2014-11-08
相关资源
最近更新 更多