Dividir string em Lua?

Eu preciso fazer uma simples divisão de uma string, mas não parece haver uma function para isso, e a maneira manual que eu testei não parece funcionar. Como eu faria isso?

Por favor, veja Splitting Strings :

Aqui estão várias maneiras de dividir uma string em uma lista de substrings, quebrando a string original em ocorrências de algum separador (caractere, conjunto de caracteres ou padrão). Isso é comumente chamado de function split [2] de string.

Aqui está a minha solução realmente simples. Use a function gmatch para capturar seqüências que contenham pelo menos UM caractere de QUALQUER coisa diferente do separador desejado. O separador é QUALQUER espaço em branco (% s em Lua) por padrão:

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 

Se você está dividindo uma string em Lua, você deve tentar os methods string.gmatch () ou string.sub (). Use o método string.sub () se você souber o índice que você deseja dividir a string, ou use o string. Se você irá analisar a string para encontrar o local para dividir a string em.

Exemplo usando string.gmatch () do Lua 5.1 Reference Manual :

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

Se você quiser apenas iterar os tokens, isso é bem legal:

 line = "one, two and 3!" for token in string.gmatch(line, "[^%s]+") do print(token) end 

Saída:

1,

dois

e

3!

Explicação breve: o padrão “[^% s] +” corresponde a todas as sequências não vazias entre caracteres de espaço.

Assim como o string.gmatch encontrará padrões em uma string, esta function encontrará as coisas entre os padrões:

 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 

Por padrão, ele retorna o que estiver separado por espaço em branco.

Aqui está a function:

 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 

Chame assim:

 list=split(string_to_split,pattern_to_match) 

por exemplo:

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

Para mais, acesse aqui:
http://lua-users.org/wiki/SplitJoin

Eu gosto desta solução curta

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

Porque há mais de uma maneira de esfolar um gato, aqui está minha abordagem:

Código :

 #!/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 

Saída : 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. 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.

Explicação :

A function gmatch funciona como um iterador, ele busca todas as strings que correspondem à regex . A regex pega todos os caracteres até encontrar um separador.

Você pode usar este método:

 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) 

Simplesmente sentado em um delimitador

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

Eu usei os exemplos acima para criar minha própria function. Mas a peça que faltava para mim era automaticamente escaping de personagens mágicos.

Aqui está minha contribuição:

 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 

Muitas dessas respostas só aceitam separadores de um único caractere, ou não lidam bem com casos de borda (por exemplo, separadores vazios), então pensei em fornecer uma solução mais definitiva.

Aqui estão duas funções, gsplit e split , adaptadas do código na extensão Scribunto MediaWiki , que é usada em wikis como a Wikipedia. O código está licenciado sob a GPL v2 . Eu mudei os nomes das variables ​​e adicionei comentários para tornar o código um pouco mais fácil de entender, e eu também mudei o código para usar os padrões normais de string Lua ao invés dos padrões do Scribunto para strings Unicode. O código original tem casos de teste aqui .

 -- 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 

Alguns exemplos da function de split em uso:

 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', '')) -- foo 

uma maneira não vista nos outros

 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