非贪婪正则表达式不符合我的预期

Non greedy regular expression not matching what I expected

我正在文本中搜索使用 "variable2" 且行前没有分号的行。这是我解决这个问题的正则表达式。

^[^;]*?variable2

我对此的理解是,它应该找到以换行符开头的文本,该换行符最小化后跟 "variable2" 的非分号字符的数量。 这未能 select 我在此示例中所期望的。


Label0: mov     variable0,WREG             ;Some comment
        mov     W0,variable1

Label1: btsc    variable2,#1               ;Some other comment
        bra     label2

我希望得到这个

Label1: btsc    variable2

但 select 编辑了这个

        mov     W0,variable1

Label1: btsc    variable2

我误会了什么?在我看来,非贪婪的表达并没有按照我的意图去做。如果我将正则表达式更改为 ^[^;\n]*?variable2,它 select 就是我期望的 select。我正在为我的正则表达式使用 Sublime Text 2,但我似乎在 php、javascript 和 python 中得到了相同的结果(根据 regex101.com)。

^[^;]*?variable2

此正则表达式匹配除 ; 之外的任何内容,从行首到 variable2。因为第 2 行和第 3 行(只是一个换行符)也不包含任何 ; 它们从第二行开始匹配到 variable2。由于您使用的是多行模式,因此 ^ 充当每行的锚点。

Demo

^[^;\n]*?variable2

此正则表达式匹配除 ;\n 之外的任何内容,从行的开头到 variable2。第 2 行和第 3 行不匹配,因为它们包含 \n.

Demo

你在这里得到了一个不正确的惰性匹配的关键点:它不试图找到整体最短的可能匹配,但它试图从头开始找到最短的可能匹配。让我们用一个更短的正则表达式来展示这一点:a*?b。给定一个字符串 aab,您期望惰性匹配匹配 ab,但它匹配 aab.

正则表达式解析器从字符串中的第一个字符(第一个 a)开始并对其进行惰性匹配。然后继续,但无法匹配 b,因为第二个字符仍然是 a。然后扩展 a*? 模式以匹配 aa,现在可以成功匹配 b,给出整体匹配 aab.

您可以使用负面前瞻

^(?:(?!;).)+variable2

参见 a demo on regex101.com(注意 multiline 修饰符!)。

^           # matches the beginning of the line
(?:(?!;).)+ # match any character except a newline
            # and make sure what immediately follows
            # is not a semicolon 
variable2   # match variable2