为什么这不是非贪婪匹配并只给我图片的名称?

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

这将给我

--> /example.com/image

但我想得到

--> image
点赞
用户3832970
用户3832970

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

[![enter image description here](https://i.stack.imgur.com/jpgWO.png)](https://i.stack.imgur.com/jpgWO.png)

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

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

请参阅在线Lua演示

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

[![enter image description here](https://i.stack.imgur.com/I4hpb.png)](https://i.stack.imgur.com/I4hpb.png)

从模式中删除第一个/并不是一个好主意,因为它会使引擎在尝试查找匹配时使用更多的冗余步骤,/将在/符号上“锚定”量化的子模式。引擎更容易找到/而不是寻找除/以外的0+(从一开始就未定义)个字符。

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

2017-06-22 22:00:11
用户107090
用户107090

如果你确定在文件名之前的字符串中有一个 /,那么这个代码可以工作:

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

贪婪匹配 .*/ 将停止在最后一个 /,达到了期望的效果。

2017-06-22 23:20:33
用户1442917
用户1442917

直接回答这个问题:.?-不能保证匹配到最短的结果,因为匹配的左侧部分仍然锚定在当前位置,如果该位置有匹配项,则会返回该匹配项作为结果。非贪婪意味着它会尽可能少地匹配其模式匹配的字符,只要匹配其余部分就可以了。这就是为什么使用[^/]-修复模式,因为它将查找未出现斜杠的最短字符数量,为什么使用.*/.-有效,因为在这种情况下,.*会贪婪地消耗所有东西,然后回溯到匹配其余部分(在这种情况下,将产生相同的结果)。

2017-06-23 05:01:10