在Lua中分割字符串?

Split string in Lua?

我需要对字符串进行简单的拆分,但是似乎没有为此功能,而且我测试的手动方式似乎无效。 我该怎么办?


这是我真正简单的解决方案。使用gmatch函数捕获包含至少一个除所需分隔符以外的任何字符的字符串。分隔符默认为** any *空格(在Lua中为%s):

1
2
3
4
5
6
7
8
9
10
function mysplit (inputstr, sep)
        if sep == nil then
                sep ="%s"
        end
        local t={}
        for str in string.gmatch(inputstr,"([^"..sep.."]+)") do
                table.insert(t, str)
        end
        return t
end


如果要在Lua中拆分字符串,则应尝试使用string.gmatch()或string.sub()方法。如果知道要分割字符串的索引,请使用string.sub()方法;如果要解析字符串以找到分割字符串的位置,请使用string.gmatch()。

使用Lua 5.1参考手册中的string.gmatch()的示例:

1
2
3
4
5
 t = {}
 s ="from=world, to=Lua"
 for k, v in string.gmatch(s,"(%w+)=(%w+)") do
   t[k] = v
 end


如果您只想遍历令牌,这很整洁:

1
2
3
4
5
line ="one, two and 3!"

for token in string.gmatch(line,"[^%s]+") do
   print(token)
end

输出:

one,

two

and

3!

简短说明:" [^%s] +"模式与空格字符之间的每个非空字符串匹配。


就像string.gmatch将在字符串中查找模式一样,此函数将在模式之间查找内容:

1
2
3
4
5
6
7
8
9
function string:split(pat)
  pat = pat or '%s+'
  local st, g = 1, self:gmatch("()("..pat..")")
  local function getter(segs, seps, sep, cap1, ...)
    st = sep and seps + #sep
    return self:sub(segs, (seps or 0) - 1), cap1 or sep, ...
  end
  return function() if st then return getter(st, g()) end end
end

默认情况下,它返回由空格分隔的所有内容。


这是函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function split(pString, pPattern)
   local Table = {}  -- NOTE: use {n = 0} in Lua-5.0
   local fpat ="(.-)" .. pPattern
   local last_end = 1
   local s, e, cap = pString:find(fpat, 1)
   while s do
      if s ~= 1 or cap ~="" then
     table.insert(Table,cap)
      end
      last_end = e+1
      s, e, cap = pString:find(fpat, last_end)
   end
   if last_end <= #pString then
      cap = pString:sub(last_end)
      table.insert(Table, cap)
   end
   return Table
end

像这样称呼它:

1
list=split(string_to_split,pattern_to_match)

例如。:

1
list=split("1:2:3:4","\:")

有关更多信息,请访问此处:
http://lua-users.org/wiki/SplitJoin


我喜欢这个简短的解决方案

1
2
3
4
5
6
7
function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end


因为有多种方法可以给猫皮毛,所以这是我的方法:

码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/usr/bin/env lua

local content = [=[
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.
]=]

local function split(str, sep)
   local result = {}
   local regex = ("([^%s]+)"):format(sep)
   for each in str:gmatch(regex) do
      table.insert(result, each)
   end
   return result
end

local lines = split(content,"
"
)
for _,line in ipairs(lines) do
   print(line)
end

输出:

Lorem ipsum dolor sit amet, consectetur adipisicing elit,
sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis nostrud exercitation
ullamco laboris nisi ut aliquip ex ea commodo consequat.

说明:

gmatch函数用作迭代器,它获取所有与regex匹配的字符串。 regex接受所有字符,直到找到分隔符。


您可以使用以下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function string:split(delimiter)
  local result = { }
  local from  = 1
  local delim_from, delim_to = string.find( self, delimiter, from  )
  while delim_from do
    table.insert( result, string.sub( self, from , delim_from-1 ) )
    from  = delim_to + 1
    delim_from, delim_to = string.find( self, delimiter, from  )
  end
  table.insert( result, string.sub( self, from  ) )
  return result
end

delimiter = string.split(stringtodelimite,pattern)

一种别人看不见的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
function str_split(str, sep)
    if sep == nil then
        sep = '%s'
    end

    local res = {}
    local func = function(w)
        table.insert(res, w)
    end

    string.gsub(str, '[^'..sep..']+', func)
    return res
end

这些答案很多都只接受单字符分隔符,或者不能很好地处理边缘情况(例如空分隔符),因此我想我会提供更确定的解决方案。

这是两个功能,gsplitsplit,是从Scribunto MediaWiki扩展中的代码改编而成的,该代码在Wikipedia等Wiki上使用。该代码是根据GPL v2许可的。我更改了变量名称并添加了注释,以使代码更易于理解,并且我还更改了代码,以使用常规Lua字符串模式而不是Scribunto的Unicode字符串模式。原始代码在这里有测试用例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
-- gsplit: iterate over substrings in a string separated by a pattern
--
-- Parameters:
-- text (string)    - the string to iterate over
-- pattern (string) - the separator pattern
-- plain (boolean)  - if true (or truthy), pattern is interpreted as a plain
--                    string, not a Lua pattern
--
-- Returns: iterator
--
-- Usage:
-- for substr in gsplit(text, pattern, plain) do
--   doSomething(substr)
-- end
local function gsplit(text, pattern, plain)
  local splitStart, length = 1, #text
  return function ()
    if splitStart then
      local sepStart, sepEnd = string.find(text, pattern, splitStart, plain)
      local ret
      if not sepStart then
        ret = string.sub(text, splitStart)
        splitStart = nil
      elseif sepEnd < sepStart then
        -- Empty separator!
        ret = string.sub(text, splitStart, sepStart)
        if sepStart < length then
          splitStart = sepStart + 1
        else
          splitStart = nil
        end
      else
        ret = sepStart > splitStart and string.sub(text, splitStart, sepStart - 1) or ''
        splitStart = sepEnd + 1
      end
      return ret
    end
  end
end

-- split: split a string into substrings separated by a pattern.
--
-- Parameters:
-- text (string)    - the string to iterate over
-- pattern (string) - the separator pattern
-- plain (boolean)  - if true (or truthy), pattern is interpreted as a plain
--                    string, not a Lua pattern
--
-- Returns: table (a sequence table containing the substrings)
local function split(text, pattern, plain)
  local ret = {}
  for match in gsplit(text, pattern, plain) do
    table.insert(ret, match)
  end
  return ret
end

split函数使用的一些示例:

1
2
3
4
5
6
7
local function printSequence(t)
  print(unpack(t))
end

printSequence(split('foo, bar,baz', ',%s*'))       -- foo     bar     baz
printSequence(split('foo, bar,baz', ',%s*', true)) -- foo, bar,baz
printSequence(split('foo', ''))                    -- f       o       o

只需坐在分隔符上

1
2
3
4
5
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
    print(x)
end


我使用上面的示例来构建自己的功能。但是对我来说,缺少的部分是自动转义魔术角色。

这是我的贡献:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function split(text, delim)
    -- returns an array of fields based on text and delimiter (one character only)
    local result = {}
    local magic ="().%+-*?[]^$"

    if delim == nil then
        delim ="%s"
    elseif string.find(delim, magic, 1, true) then
        -- escape magic
        delim ="%"..delim
    end

    local pattern ="[^"..delim.."]+"
    for w in string.gmatch(text, pattern) do
        table.insert(result, w)
    end
    return result
end


您可以使用penlight库。它具有使用定界符分割字符串的功能,该定界符输出列表。

它已经实现了我们在Lua中编程和缺少时可能需要的许多功能。

这是使用它的示例。

1
2
3
4
5
6
7
8
9
10
>
> stringx = require"pl.stringx"
>
> str ="welcome to the world of lua"
>
> arr = stringx.split(str,"")
>
> arr
{welcome,to,the,world,of,lua}
>

根据使用情况,这可能会很有用。它在标志的两边剪切所有文本:

1
2
3
4
5
6
b ="This is a string used for testing"

--Removes unwanted text
c = (b:match("a([^/]+)used"))

print (c)

输出:

1
string