为什么这不非贪婪地匹配并只给我图像名称?

Why doesn't this match non-greedily and give me just the image name?

local s = "http://example.com/image.jpg"
print(string.match(s, "/(.-)%.jpg"))

这给了我

--> /example.com/image

但我想要

--> image

由于正则表达式引擎从左到右处理字符串,您的模式找到第一个 /,然后 .- 匹配尽可能少的任何字符 (.) (-) 到第一个文字 .(与 %. 匹配)后跟 jpg 子字符串。

您需要使用否定字符 class [^/](以匹配除 / 之外的任何字符)而不是匹配任何字符的 .

local s = "http://example.com/image.jpg"
print(string.match(s, "/([^/]+)%.jpg"))
-- => image

online Lua demo

[^/] 匹配任何字符 /,因此,最后一个 / 将与第一个 / 匹配] 在模式 "/([^/]+)%.jpg" 中。它将匹配为

从模式中删除第一个 / 不是一个好主意,因为它会使引擎在尝试查找匹配项时使用更多冗余步骤,/ 将 "anchor" / 符号处的量化子模式。引擎找到 / 比查找 /.

以外的 0+(从头开始未定义)个字符更容易

如果您确定此字符串出现在字符串的末尾,请在模式末尾添加 $(实际上您是否需要这样做并不清楚,但在一般情况下可能是最好的).

如果您确定文件名之前的字符串中有一个 /,则可以这样做:

print(string.match(s, ".*/(.-)%.jpg"))

贪婪匹配 .*/ 将根据需要在最后 / 处停止。

Why doesn't this match non-greedily and give me just the image name?

直接回答问题:.-不保证最短匹配,因为匹配的左边部分仍然锚定在当前位置,如果在那个位置匹配到某些东西,它将被返回作为结果。非贪婪只是意味着只要模式的其余部分匹配,它将消耗最少数量的与其模式匹配的字符。这就是为什么使用 [^/]- 可以修复模式,因为它会找到最短数量的非正斜杠字符,以及为什么使用 .*/.- 会像在这种情况下一样工作 .* 会贪婪地消耗所有内容然后回溯直到满足模式的其余部分(在这种情况下将产生相同的结果)。