复杂的字符串替换问题

时间:2016-01-09 02:46:43

标签: string replace lua

我正在尝试用其他文字替换一些文字。简单吧?嘿。

首先,我有一串文字:

local str = "This is some >>1234 text. This is some >>>/other/1234 text."

你会在文本中注意到有趣的格式。我需要用HTML替换它们。但有一个问题:我需要使用该格式中的数据访问数据库。我使用以下格式来获取数据:

local pattern1 = ">>(%d+)"
local pattern2 = ">>>/(%w+)/(%d*)"

在这两种模式中,我都需要使用%d部分来检查数据库。原因在于,根据数据,我需要以不同方式格式化链接。最终,我希望有这样的东西:

local formatted = "This is some <a href='website.com/a/1220#1234'>>>1234</a> text. This is some <a href='website.com/other/1156#1234'>>>>/other/1234</a> text."

所以我第一次尝试在string.gsub中对匹配的每个实例运行一个函数。这导致了C-yield错误,因为我试图访问协程中的C junk(数据库驱动程序),正如我所知,这是一个禁忌。

我不确定我的第二次尝试应该是什么。我想我需要使用string.match迭代文本来提取我想要抓取的地方的索引,然后使用gsub获取我需要访问数据库并存储在某处的数据,然后从头开始重建字符串。

这是正确的,还是有更好的方法?

Error

attempt to yield across C-call boundary
Traceback

stack traceback:
    [C]: in function 'receive'
    /home/karai/.luarocks/share/lua/5.1/pgmoon/init.lua:419: in function 'receive_message'
    /home/karai/.luarocks/share/lua/5.1/pgmoon/init.lua:233: in function 'query'
    /usr/share/lua/5.1/lapis/db/postgres.lua:64: in function 'select'
    ./src/text_formatter.lua:39: in function <./src/text_formatter.lua:24>
    [C]: in function 'gsub'
    ./src/text_formatter.lua:55: in function 'quote'
    ./src/board.lua:58: in function 'handler'
    /usr/share/lua/5.1/lapis/application.lua:399: in function 'resolve'
    /usr/share/lua/5.1/lapis/application.lua:408: in function </usr/share/lua/5.1/lapis/application.lua:406>
    [C]: in function 'xpcall'
    /usr/share/lua/5.1/lapis/application.lua:406: in function 'dispatch'
    /usr/share/lua/5.1/lapis/nginx.lua:205: in function 'serve'
    content_by_lua(nginx.conf.compiled:27):2: in function <content_by_lua(nginx.conf.compiled:27):1>

1 个答案:

答案 0 :(得分:4)

您的问题的核心似乎是您希望在每次匹配时产生(大概是在数据库查询完成之前),然后继续处理。

为此,您应首先使用gmatch。它执行gsub所做的事情,但没有替换;它返回一个迭代器,你可以循环返回匹配。因此,使用它来生成查询列表。这应该存储在一个数组中:

local matches = {}
for match in my_string:gmatch(pattern) do
  matches[#matches + 1] = match
end

然后只需走数组,做你的数据库/产量。

local repls = {}
for i, match in ipairs(matches) do
  --Do database query&yield stuff with `match`.
  repls[i] = --Generate the data you want to replace this match with.
end

之后,只需gsub替换字符串即可。与gmatchgsub匹配的顺序是相同的,因此您无需关心参数:

local i = 0 --Not zero-based; keep reading
local fixed_string = my_string:gsub(pattern,
  function() --Don't care about the arguments.
    i = i + 1
    return repls[i] --Started at zero, so that this would be correct.
  end
)