正则表达式中 (.*?) 和 (.*) 有什么区别?

18

我已经做了一段时间的正则表达式,但是对于特定规则的微妙差别并不是专家级。 我一直使用(.*?)进行匹配,但有限制条件,因为我理解它会在第一次机会时停止匹配,而(.*)?会继续匹配且更具贪心性。

但我没有真正的理由认为这样,只是因为我曾经读过一次。

现在我想知道,这两者有区别吗?如果有,是什么呢...


1
? 多余了!因为 (.*) 会匹配零到多个字符。 - Anirudha
4个回答

14

(.*?) 是一个包含非贪婪匹配的组。

(.*)? 是一个可选组,其中包含贪婪匹配。


所以你的意思是,(1) 表示有一个组,只是非贪婪的,而 (2) 表示可能有一个组,也就是说它可能不返回任何内容。因此,由于我总是使用 (1),我基本上要求它以非贪婪的方式找到一些东西,这可能解释了为什么有时正则表达式无法匹配任何内容,因为我要求至少有一个匹配。对吗? - Christopher Thomas
@ChristopherThomas:不行,因为.*?也可以匹配空。 - SLaks
4
你能解释一下贪婪和非贪婪的区别吗? - Philipp

7

有人指出了贪婪匹配和非贪婪匹配之间的区别。下面是一个实际应用中可以看到不同结果的示例。由于正则表达式通常嵌入在主机语言中,我将使用Perl作为主机。在Perl中,将匹配项括在括号中会将这些匹配项的结果分配给特殊变量。因此,在这种情况下,匹配可能相同,但分配给这些变量的内容可能不同:

例如,假设您的匹配字符串是“hello”。两个模式都可以匹配它,但匹配的部分($1)不同:

'hello' =~ /(.*?)l/;
# $1 == 'he' 

'hello' =~ /(.*)?l/;
# $1 == 'hel'

区别在于?)定义了一个非贪婪量词,这意味着匹配结果将不同。当然,正如你所提到的,)?是非匹配的,但这并不是完整的答案。 - Nir Levy
我其实不太确定你在这里的意思......你能用另一种方式解释一下吗?感谢你的耐心! - Christopher Thomas

6
因为 * 表示“零个或多个”,这让事情有点混淆。两个 ? 是完全不同的,可以通过下面每个例子更清楚地展示: fo*? 只会匹配 f,如果你提供了 foo。也就是说,这个 ? 使匹配变得非贪婪。将它移除后,它将匹配 foofo? 匹配 f,但也匹配 fo。也就是说,这个 ? 使匹配变得可选:它所应用于的部分(在本例中仅为 o)必须出现 0 次或 1 次。将它移除后,匹配将变得必选:它必须恰好出现一次,因此只有 fo 仍然匹配。
另外,在正则表达式中,当我们谈到 ? 的不同含义时,还有一个意思:紧跟在 ( 后面的 ? 是几个特殊操作的前缀,例如 lookaround。也就是说,它的意义不像你问的任何一件事。

5

? 有不同的含义。

  1. 当它跟在一个字符或组后面时,它是一个量词,匹配前面构造体的 0 或 1 次出现。详见这里

  2. 当它跟在一个量词后面时,它会修改该量词的匹配行为,使其变为懒惰匹配。详见这里


那么在(1)中,它表示它将返回某些东西,但可能是空字符串?空字符串是正则表达式的有效返回吗?我认为不是,但现在我看到是这样的。 - Christopher Thomas
如果允许模式匹配空字符串,则它是一个有效的返回值。模式.*只有作为子模式才有意义,否则它没有意义,因为它匹配所有内容。如果您想匹配至少一个字符,则+将是正确的选择,它匹配一个或多个字符。也许您会对我写的博客文章感兴趣:你真的了解量词吗? - stema
嗨Stema,我喜欢你的文章,发现它非常有用,而且额外提供了关于“重复”方面的re.info网站链接。我从中学到的是,.*?形式表示尽可能懒惰地匹配,这样就可以最小化匹配次数,包括零/空。所以这就解释了为什么它在我的例子和用法中起作用。 - Christopher Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接