为什么 Lua 的 string.gsub 函数无法从变量取替换模式?

在以下 Lua 代码中,我试图实现一个选择器语法,根据“Minecraft”的“世界”来更改值,在找到“木材”之后。但是gsub函数似乎从未将选择器值作为输入,总是表现为给定%1一样。

local woodTypeWorld = {
  Oak = 'overworld',
  Crimson = 'nether',
}
local item = '${Log,Stem}'
-- 强制迭代顺序
for _, wood in ipairs({'Oak', 'Crimson'}) do
  -- 解析${,}(世界选择)语法
  local selector = (woodTypeWorld[wood] == 'overworld') and "%1" or "%2"
  print(woodTypeWorld[wood] .. " -> " .. selector)
  item = item:gsub("%${(.-),(.-)}", selector)
  print(wood .. ' ' .. item)
end

换句话说,我期望的输出是:

overworld ->% 1
Oak Log
nether ->% 2
Crimson Stem

实际得到的输出是:

overworld -> %1
Oak Log
nether -> %2
Crimson Log

这是在Gamepedia实例中的MediaWiki Lua,Lua的repl.it实例以及Lua语言的官方[demo页面](https://www.lua.org/cgi -bin/demo)。我已尝试过以下内容,但均无效:

-将选择器重写为函数 function(_,o,n)(woodTypeWorld [wood] =='overworld')and o or n end -将伪三元和/或语句扩展到if -在gsub列表中添加“,1” -从三元表达式确定的数字和“%”组装选择器 -显式调用string.gsub或MediaWiki的特殊UTF-8支持的mw.ustring.gsub

此外:

-当选择器被替换为字符串文本时,gsub的效果如所述。 -如果ipairs顺序被颠倒,则输出会更改为全“Stem”。就像选择器已缓存一样。

点赞
用户7509065
用户7509065

问题在于循环的第一次迭代改变了 item,然后它在接下来的所有迭代中都保持了改变状态,因为它不再符合模式。为了解决这个问题,不要覆盖它,而是将 gsub 的结果保存到另一个变量中,像这样:

local woodTypeWorld = {
  Oak = 'overworld',
  Crimson = 'nether',
}
local item = '${Log,Stem}'
-- 强制迭代顺序
for _, wood in ipairs({'Oak', 'Crimson'}) do
  -- 解析 ${,}(world-select)语法
  local selector = (woodTypeWorld[wood] == 'overworld') and "%1" or "%2"
  print(woodTypeWorld[wood] .. " -> " .. selector)
  local item2 = item:gsub("%${(.-),(.-)}", selector)
  print(wood .. ' ' .. item2)
end
2020-05-24 04:55:09