Perl:将带有贪婪量词的正则表达式转换为非贪婪的方法
我的用户给出了一个带有默认为贪婪的量词的正则表达式。他可以给出任何有效的正则表达式。因此,解决方案必须处理用户可以扔给我的任何东西。
如何转换正则表达式,以便任何贪婪的量词都是非贪婪的?
Perl 是否有一种(?...:regexp)结构可以将量词的贪婪默认值强制转换为非贪婪的?
如果不是:有没有一种不同的方法可以将带有贪婪量词的正则表达式强制转换为非贪婪量词?
例如,用户可以输入:
.*
[.*]
[.*]{4,10}
[.*{4,10}]{4,10}
尽管这四个示例看起来相似,但它们的含义却完全不同。
如果您只是?在每个*/之后添加,}您将更改最后三个示例中的字符集。
相反,它们应该更改为/表现如下:
.*?
[.*]
[.*]{4,10}?
[.*{4,10}]{4,10}?
但是如果匹配的字符串是最小匹配,而不是第一个匹配,Perl 将默认为:
$a="aab";
$a=~/(a.*?b)$/;
# Matches aab, not ab
print $1;
但是考虑到非贪婪的正则表达式,最小匹配可能可以通过预先获得.*:
$a="aab";
$a=~/.*(a.*?b)$/;
# Matches ab
print $1;
回答
“贪婪”不是整个正则表达式的属性,而是量词的属性。
可以对每个量词分别进行控制。只需?在量词后添加 a即可使其不贪婪,例如
[a-z]*?
a{2,3}?
[0-9]??
s+?
不,没有内置的方法可以将整个正则表达式转换为某种“默认非贪婪”模式。您需要解析正则表达式,检测所有量词并相应地更改它们。也许 CPAN 上有一个正则表达式解析库。
到目前为止,我发现的最接近的是Regexp::Parser 模块。我没有尝试过,但看起来它可以解析正则表达式,遍历树,进行适当的更改,然后构建修改后的正则表达式。请看一下。
- @Ole Tange, Asking us to write a regex parser is *way* too broad, and asking for library/tools recommendations is also off-topic.