Разделить строку в Lua?

Мне нужно сделать простой разбиение строки, но, похоже, для этого нет функции, и ручной способ, который я тестировал, похоже, не работал. Как мне это сделать?

13 ответов


см. Разбиение Строки:

вот различные способы разделения a строка в список подстрок, разрыв исходной строки на вхождения некоторого разделителя (символ, набор символов, или узор.) Это обычно называется функция разделения строк[2].


вот мое простое решение. Используйте функцию gmatch для захвата строк, содержащих по крайней мере один символ чего-либо, кроме нужного разделителя. По умолчанию разделителем является любой пробел (%s в Lua):

function mysplit(inputstr, sep)
        if sep == nil then
                sep = "%s"
        end
        local t={} ; i=1
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                t[i] = str
                i = i + 1
        end
        return t
end

Если вы разделяете строку в Lua, вы должны попробовать строку.gmatch() или String.суб() методы. Используйте строку.метод sub (), если вы знаете индекс, в котором хотите разделить строку, или используете строку.gmatch () если вы проанализируете строку, чтобы найти место для разделения строки.

пример использования string.gmatch() из Справочное Руководство Lua 5.1:

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

Если вы просто хотите перебирать токены, это довольно аккуратно:

line = "one, two and 3!"

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

выход:

один,

два

и

3!

краткое объяснение: шаблон" [^%s]+ " соответствует каждой непустой строке между пробелами.


как string.gmatch найти шаблоны в строке эта функция найдет вещи между модели:

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

по умолчанию он возвращает все, что отделено пробелом.


вот функция:

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

назовите это так:

list=split(string_to_split,pattern_to_match)

например:

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


Для большего идите сюда:
http://lua-users.org/wiki/SplitJoin


Мне нравится это короткое решение

function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

потому что есть несколько способов освежевать кошку, вот мой подход:

код:

#!/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, "\n")
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. The regex принимает все символы, пока не найдет сепаратора.


вы можете использовать этот метод:

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) 

просто сидя на разделитель

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

я использовал приведенные выше примеры для создания собственной функции. Но недостающая часть для меня автоматически ускользала от магических персонажей.

вот мой вклад:

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

не видел в других

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

многие из этих ответов принимают только односимвольные разделители или не имеют дело с краевыми случаями (например, пустые разделители), поэтому я подумал, что предоставлю более окончательное решение.

вот две функции,gsplit и split, адаптированный код на расширение Scribunto MediaWiki, который используется в проекте, как Википедия. Код лицензируется в соответствии с GPL версии 2. Я изменил имена переменных и добавил комментарии к сделайте код немного проще для понимания, и я также изменил код, чтобы использовать обычные шаблоны строк Lua вместо шаблонов Scribunto для строк Unicode. Исходный код и тесты здесь.

-- 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 функции В использовать:

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