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

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

145 голосов
/ 15 сентября 2009

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

Ответы [ 12 ]

76 голосов
/ 30 сентября 2011

Вот мое действительно простое решение. Используйте функцию gmatch для захвата строк, которые содержат как минимум ОДИН символ НИЧЕГО, кроме требуемого разделителя. Разделителем является ЛЮБОЙ пробел (% s в Lua) по умолчанию:

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
31 голосов
/ 15 сентября 2009

Если вы разбиваете строку в Lua, вам следует попробовать методы string.gmatch () или string.sub (). Используйте метод string.sub (), если вам известен индекс, по которому вы хотите разделить строку, или используйте string.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
23 голосов
/ 12 сентября 2010

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

line = "one, two and 3!"

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

Выход:

один

два

и

3!

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

14 голосов
/ 30 октября 2009

Так же, как 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

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

11 голосов
/ 16 октября 2009

Вот функция:

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 / вики / SplitJoin

7 голосов
/ 20 ноября 2013

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

function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end
6 голосов
/ 22 августа 2014

Поскольку существует более одного способа снятия шкур с кошки, вот мой подход:

Код :

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

5 голосов
/ 17 февраля 2011

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

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) 
4 голосов
/ 24 апреля 2017

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

Здесь представлены две функции gsplit и split, адаптированные из кода в расширении Scribunto MediaWiki , которое используется в вики, например, в Википедии. Код предоставляется по лицензии GPL v2 . Я изменил имена переменных и добавил комментарии, чтобы сделать код немного легче для понимания, и я также изменил код, чтобы использовать обычные строковые шаблоны 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
4 голосов
/ 27 апреля 2016

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

local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
    print(x)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...