gpt4 book ai didi

regex - 为什么这个递归正则表达式不捕获整个代码块?

转载 作者:行者123 更新时间:2023-12-04 20:43:26 25 4
gpt4 key购买 nike

我正在尝试编写一个递归正则表达式来捕获代码块,但由于某种原因,它似乎没有正确捕获它们。我希望下面的代码能够捕获函数的全部内容,但它只捕获第一个 if 的内容陈述。

这几乎就像 .+?不知何故吞噬了第一个 { ,但它应该是非贪婪的,所以我不明白为什么会这样。

是什么导致它以这种方式行事?

脚本:

use strict;
use warnings;

my $text = << "END";
int max(int x, int y)
{
if (x > y)
{
return x;
}
else
{
return y;
}
}
END

# Regular expression to capture balanced "{}" groups
my $regex = qr/
\{ # Match opening brace
(?: # Start non-capturing group
[^{}]++ # Match non-brace characters without backtracking
| # or
(?R) # Recursively match the entire expression
)* # Match 0 or more times
\} # Match closing brace
/x;

# is ".+?" gobbling up the first "{"?
# What would cause it to do this?
if ($text =~ m/int\s.+?($regex)/s){
print $1;
}

输出:
{
return x;
}

预期输出:
{
if (x > y)
{
return x;
}
else
{
return y;
}
}

我知道有一个 Text::Balanced 用于此目的的模块,但我正在尝试手动执行此操作以了解有关正则表达式的更多信息。

最佳答案

(?R)递归到整个模式——但整个模式是什么?当您嵌入引用的 $regex进入 /int\s.+?($regex)/ , 模式被重新编译和 (?R)指新模式。那不是你想要的。

我建议您改用命名捕获,以便您可以按名称递归。更改$regex

/(?<nestedbrace> ... (?&nestedbrace) ...)/

如果你想避免额外的捕获,你可以使用 (?(DEFINE) ...)声明可以稍后调用的命名正则表达式模式的语法:
my $define_nestedbrace_re = qr/(?(DEFINE)
(?<nestedbrace ... (?&nestedbrace) ...)
)/x;

然后: /int\s.+?((?&nestedbrace))$define_nestedbrace_re/
这不会创建额外的捕获。但是,通常不可能编写封装的正则表达式片段。喜欢命名捕获而不是编号捕获之类的技术可以在这里提供帮助。

关于regex - 为什么这个递归正则表达式不捕获整个代码块?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46118290/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com