【问题标题】:Split string with specified delimiter in lua在lua中使用指定的分隔符拆分字符串
【发布时间】:2020-07-24 01:51:30
【问题描述】:

我正在尝试在 lua 中创建一个带有分隔符的 split() 函数,默认为空格。 默认工作正常。当我为函数指定分隔符时,问题就开始了。由于某种原因,它不会返回最后一个子字符串。 功能:

function split(str,sep)
if sep == nil then
    words = {}
    for word in str:gmatch("%w+") do table.insert(words, word) end
    return words
end
return {str:match((str:gsub("[^"..sep.."]*"..sep, "([^"..sep.."]*)"..sep)))} -- BUG!! doesnt return last value
end

我尝试运行这个:

local str = "a,b,c,d,e,f,g"
local sep = ","
t = split(str,sep)
for i,j in ipairs(t) do
    print(i,j)
end

我得到:

1   a
2   b
3   c
4   d
5   e
6   f

无法弄清楚错误在哪里......

【问题讨论】:

标签: regex lua


【解决方案1】:

在拆分字符串时,避免极端情况的最简单方法是在字符串不能以分隔符结尾时附加分隔符:

str = "a,b,c,d,e,f,g"
str = str .. ','
for w in str:gmatch("(.-),") do print(w) end

或者,您可以使用带有可选分隔符的模式:

str = "a,b,c,d,e,f,g"
for w in str:gmatch("([^,]+),?") do print(w) end

实际上,我们不需要可选的分隔符,因为我们正在捕获非分隔符:

str = "a,b,c,d,e,f,g"
for w in str:gmatch("([^,]+)") do print(w) end

【讨论】:

  • 如此简单优雅...谢谢!
  • 我认为在字符串中附加一个分隔符在任何情况下都有效,不仅仅是当字符串不能以分隔符结尾时。如果字符串以分隔符结尾,您将得到一个空的最后一个匹配项,这应该是意料之中的。
  • @tonypdmtr,当然,只要你清楚这一点就可以了。
  • @lhf,你为什么在模式末尾使用,??不管有没有,结果都是一样的。
  • 这应该被添加到官方 Lua 文档中。网上有太多帖子把这个简单的问题变成了代码高尔夫倒置。
【解决方案2】:

这是我的首选 split() 函数:

-- split("a,b,c", ",") => {"a", "b", "c"}
function split(s, sep)
    local fields = {}
    
    local sep = sep or " "
    local pattern = string.format("([^%s]+)", sep)
    string.gsub(s, pattern, function(c) fields[#fields + 1] = c end)
    
    return fields
end

【讨论】:

    【解决方案3】:

    "[^"..sep.."]*"..sep 这就是导致问题的原因。您正在匹配的字符串不是分隔符后跟分隔符。但是,您要匹配的最后一个子字符串 (g) 后面没有分隔符。

    解决此问题的最快方法是同时考虑 \0 分隔符 ("[^"..sep.."\0]*"..sep),因为它代表字符串的开头和/或结尾。这样,g 后面没有分隔符但在字符串末尾仍将被视为匹配项。

    我想说您的方法总体上过于复杂;首先,您可以匹配不包含分隔符的单个子字符串;其次,您可以使用gmatch 函数在for-loop 中执行此操作

    local result = {}
    for field in your_string:gsub(("[^%s]+"):format(your_separator)) do
      table.insert(result, field)
    end
    return result
    

    编辑:上面的代码更简单了一点:

    local pattern = "[^%" .. your_separator .. "]+"
    for field in string.gsub(your_string, pattern) do
    -- ...and so on (The rest should be easy enough to understand)
    

    EDIT2:请记住,您还应该转义分隔符。如果您不将其转义为 %%,则像 % 这样的分隔符可能会导致问题

    function escape(str)
      return str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-01
      • 1970-01-01
      • 2010-11-28
      • 2018-06-01
      相关资源
      最近更新 更多