为什么 perl 正则表达式不像我需要的那样贪婪?

Why isn't the perl regex being as greedy as I need it to be?

所以显示这个字符串:

!NAME: "Slot 10 SubSlot 0"

最后一个引号后面可能有一些内容,但这与手头的任务无关。

目标是,我想捕获 Slot UP 之后的所有内容,直到最后的引号。

我已经为任务尝试了两个正则表达式

/^!NAME:\s+\".*(Slot[\w|\s|\d+]+)\"/;

其他:

/^!NAME:\s+\".*(Slot.+)\"/;

但这些只捕获

Slot 0

Slot 之后的内容可能截然不同。它可能是这样的:

'Slot 4' (this works, but the capture string will not always be this small)

'Slot 4 Subslot 12 Internal Subslot 14 External'

'Slot 75 Internal Slot 12 External'

我们唯一确定的是我们想要的部分将以 'Slot' 开头,并以引号结尾。介于两者之间的任何其他事情都悬而未决。

我展示的有什么问题吗?尤其是第二个,因为我认为“。”运营商很贪婪,会尽可能多地捕获?

此脚本的目的是捕获这些细节以在另一个程序中进行解析。

贪婪。

/^!NAME:\s+\".*(Slot[\w|\s|\d+]+)\"/;
             ^^
              |----- The greedy part is here.

由于您的目标字符串在两个地方与 Slot \d+ 匹配,因此引号后的 .* 吞掉了第一个。尝试使表达式的那部分成为非贪婪的:

/!NAME:\s+\".*?(Slot(?:\w|\s|\d+)+)\"/

这应该捕获不是在 Slot 之后但在引号之前的引号的所有内容:

/^!NAME:\s+\"Slot([^\"]*)\"/

如果您出于某种原因需要它,还可以包含 Slot 部分

/^!NAME:\s+\"(Slot[^\"]*)\"/

这适用于您的所有示例文本:

^!NAME:\s*"(Slot.*?)"

https://regex101.com/r/hB1cT3/2

注意:除了 "Slot" 文本外,您所有的示例都不包含任何引号,那么为什么要将 .* 作为引号中的第一部分?正如暴民上面提到的,这就是造成问题的原因。我已经把它删除了。

这是一个简单的解决方案:

/(Slot[^"]+)/

这是实际操作:

my $s = '!NAME: "Slot 10 SubSlot 0"';
$s =~ /(Slot[^"]+)/;
print ;

# Slot 10 SubSlot 0

如果需要指定以!NAME:开头的行,那么就展开成这样:

/^!NAME:\s"(Slot[^"]+)/

最安全的答案:

/^ !NAME: \s* " (?:(?!Slot).)* Slot ( [^"]* ) "/x

您还可以确保 Slot 不是另一个词的一部分:

/^ !NAME: \s* " (?:(?!Slot).)* \b Slot \b ( [^"]* ) "/x

诀窍是知道 (?:(?!STRING).)*STRING 就像 [^CHAR]*CHAR.