使用 Lua 中带有多个返回值的表达式的逻辑运算符

我想要做这样的操作:

s,e = string.find(str, pattern1) or string.find(str, pattern2)

(因为 Lua 模式没有正则表达式的等效符号“|”)

但是这给了我一个“nil”值,即使其中一个模式匹配。

我怎么才能从第一个函数调用中获取两个返回值匹配?

原文链接 https://stackoverflow.com/questions/71083796

点赞
stackoverflow用户573255
stackoverflow用户573255

Lua的列表很脆弱,如果在非常特定的上下文之外用作表达式(最重要的是,如果它们分配给多个名称或作为函数的最后一个参数),它们会退化为它们的第一个值。为了获得所需的行为,您需要确保存储所有值。例如:

local s1, e1 = string.find(str, pattern1)
if s1 then
    s, e = s1, e1
else
    s, e = string.find(str, pattern2)
end
2022-02-11 17:07:09
stackoverflow用户2858170
stackoverflow用户2858170

因为你的函数调用不是列表表达式中的唯一或最后一个,所以它们的返回值列表被调整为一个值。

参见 https://www.lua.org/manual/5.4/manual.html#3.4

因此,

s, e = string.find(str, pattern1) or string.find(str, pattern2)

可以认为是等效于

do
  local v1 = string.find(str, pattern1)
  if v1 then
    s, e = v1, nil
  else
    local v2 = string.find(str, pattern2)
    if v2 then
      s, e = v2, nil
    else
     s, e = nil, nil
    end
  end
end

假设第一个模式匹配,那么 v1 是一个真值。 or 语句是被短路的,所以你分配

s, e = v1, nil

如果第一个模式不匹配,则调用第二个 string.find。如果有匹配的话,它的返回值是一个真值

s, e = nil or v2, nil

如果第一个模式不匹配且第二个模式也不匹配,则分配

s, e = nil, nil

你需要分别处理两个 string.find 调用,以便不丢失任何返回值。

local v1, v2 = string.find(str, pattern1)
if not v1 then
  v1, v2 = string.find(str, pattern2)
end
s, e = v1, v2
2022-02-11 17:22:57