有没有解决这个gsub()问题的聪明思路?(使用Lua进行HTML清理)

我正在尝试编写一个函数,用于消毒 HTML 文本。问题定义:

function f(txt) return txt:gsub("%s"," ")

现在,这适用于以下情况:

f(" hello  buddy!") ---> " hello  buddy!"

但根据 HTML 规范,只有当有两个或两个以上的空格时,额外的空格才需要用   替换。因此,单个空格不需要替换。如果有更多,一个空格将不会转换,但其余部分将转换为  。换句话说,我需要一个函数:

f(" hello  buddy!") ---> " hello  buddy!"
f("   ") ---> "  &nbsp"
f(" ") ---> " "
f("hello buddy!") ---> "hello buddy!"

有什么想法如何编写 f() 吗?

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

点赞
stackoverflow用户513763
stackoverflow用户513763

你可以尝试类似于以下代码的操作:

txt:gsub("( +)", function(c) return " "..(" "):rep(#c-1) end)
2011-08-29 08:15:28
stackoverflow用户796584
stackoverflow用户796584

感谢 jpjacobs 的提示,以下是完整的函数代码及示例:

---该函数将 HTML 字符串清理,使以下字符在浏览器中正确显示:
-- & 将被替换为 &
-- < 将被替换为 &lt;
-- > 将被替换为 &gt;
-- \n 将被替换为 <br/>;
-- (一个以上的空格)将被替换为 &nbsp;(根据需要重复多次)
-- @param txt 可能带有 HTML 格式化字符的输入文本
-- @return 已清理的 HTML 代码
function sanitize(txt)
    txt = txt:gsub("%&","&amp;")
    txt = txt:gsub("%<","&lt;")
    txt = txt:gsub("%>","&gt;")
    txt = txt:gsub("\n","<br/>")
    txt = txt:gsub("(% +)", function(c) return " " .. ("&nbsp;"):rep(#c-1) end)
    return txt
end

text=[[    <html>   hello  &bye </html> ]]

print("Text='" .. text .. "'")
print("sanetize='" .. sanitize(text) .. "'")

输出:

Text='    <html>   hello  &bye </html> '
sanetize=' &nbsp;&nbsp;&nbsp;&lt;html&gt; &nbsp;&nbsp;hello &nbsp;&amp;bye &lt;/html&gt; '
2011-08-29 08:28:49
stackoverflow用户501459
stackoverflow用户501459

关于 Alex 的答案的注释。在这里发布,以便包含格式化代码。

前 4 个 gsub 调用可以被替换为一个调用,它将一个查找表作为它的第二个参数。这比对代码进行 4 次遍历要快得多。

function sanitize(txt)
    local replacements = {
        ['&' ] = '&amp;',
        ['<' ] = '&lt;',
        ['>' ] = '&gt;',
        ['\n'] = '<br/>'
    }
    return txt
        :gsub('[&<>\n]', replacements)
        :gsub(' +', function(s) return ' '..('&nbsp;'):rep(#s-1) end)
end
2011-08-29 21:27:00