Lua string.match 的模式有问题吗?

我正在为 Lua 编写一个命令行解析器,并希望使用 Lua string.match() 提取选项的名称和值。

一个命令行选项被定义为:**--name=value**

以下是我使用的代码(可以在这里找到):

local expr = '--username=John'
local name, value = expr:match( '^%-%-(.*)=%"?(.*)%"?' )
print( "found values for '" .. expr .. "'")
print( name .. " = " .. value )

输出是正确的:

found values for '--username=John'
username = John

但是,如果我想设置一个带有空格的值,我会用双引号将它括起来

local expr = '--username="John Doe"'
local name, value = expr:match( '^%-%-(.*)=%"?(.*)%"?' )
print( "found values for '" .. expr .. "'")
print( name .. " = " .. **value )

输出不是我想要的,因为最后一个双引号被 string.match() 提取了

found values for '--username="John Doe"'
username = John Doe"

我的模式是否有误,还是它是 Lua 的一个 bug?

点赞
用户3832970
用户3832970

没有 bug,你的模式包含一个贪婪的 .* 模式,它会尽可能地匹配任意字符的多个实例。它抓取了整个字符串,然后回溯以查看是否有其他强制性的子模式要生成文本。因为 "? 可以匹配空字符串,所以它匹配了在 " 后面的空字符串,然而 " 却被捕获了。

有几种解决方法,下面是两种:

name, value = expr:match( '^%-%-(.*)="?([^"]*)"?' )

或者

name, value = expr:match( '^%-%-(.*)="?(.-)"?$' )

查看在线演示,输出

found values for '--username="John Doe"'
username = John Doe

细节

  • 第一个方法使用了非字符类,([^"]*)。它匹配除 " 以外的任何 0 个或多个字符。因此,它不能匹配最后的 "
  • 第二个方法使用了懒惰的 .-,它尽可能少地匹配0个或多个字符,直到但不包括字符串末尾的 "(如果存在)。
2017-08-25 15:04:46