Respostas:
Aqui está minha solução realmente simples. Use a função gmatch para capturar cadeias que contenham pelo menos um caractere de outra coisa que não seja o 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={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, str)
end
return t
end
.
'foo,,bar'
. Você obtém, em {'foo','bar'}
vez de{'foo', '', 'bar'}
function split(inputstr, sep) sep=sep or '%s' local t={} for field,s in string.gmatch(inputstr, "([^"..sep.."]*)("..sep.."?)") do table.insert(t,field) if s=="" then return t end end end
Se você estiver dividindo uma string em Lua, tente os métodos string.gmatch () ou string.sub (). Use o método string.sub () se você souber o índice no qual deseja dividir a string ou use o string.gmatch () se você analisará a string para encontrar o local em que ela será dividida.
Exemplo usando string.gmatch () do Manual de referência do Lua 5.1 :
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Se você deseja apenas iterar sobre os tokens, isso é bastante interessante:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Resultado:
1,
dois
e
3!
Breve explicação: o padrão "[^% s] +" corresponde a todas as seqüências não vazias entre os caracteres de espaço.
%S
é igual ao que você mencionou, assim como %S
a negação de %s
, assim como %D
a negação de %d
. Além disso, %w
é igual a [A-Za-z0-9_]
(outros caracteres podem ser suportados dependendo do seu código do idioma).
Assim como string.gmatch
encontrará padrões em uma string, esta função 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ços em branco.
Aqui está a função:
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 informações, acesse:
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
Como há mais de uma maneira de esfolar um gato, eis a 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.
Explicação :
A gmatch
função funciona como um iterador, busca todas as strings correspondentes regex
. A regex
toma 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)
Muitas dessas respostas aceitam apenas separadores de caractere único ou não lidam bem com casos extremos (por exemplo, separadores vazios); portanto, 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 é licenciado sob a GPL v2 . Alterei os nomes das variáveis e adicionei comentários para tornar o código um pouco mais fácil de entender, e também alterei o código para usar padrões regulares de strings Lua em vez dos padrões de 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 split
função 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', '')) -- f o o
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 função. Mas a peça que faltava para mim estava escapando automaticamente dos personagens mágicos.
Aqui está a 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
Você poderia usar a biblioteca do penlight . Isso tem uma função para dividir string usando o delimitador que gera a lista.
Ele implementou muitas das funções que podemos precisar durante a programação e a falta em Lua.
Aqui está a amostra para usá-lo.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
É tarde demais para esta pergunta, mas caso alguém queira uma versão que lide com a quantidade de divisões que você deseja obter .....
-- Split a string into a table using a delimiter and a limit
string.split = function(str, pat, limit)
local t = {}
local fpat = "(.-)" .. pat
local last_end = 1
local s, e, cap = str:find(fpat, 1)
while s do
if s ~= 1 or cap ~= "" then
table.insert(t, cap)
end
last_end = e+1
s, e, cap = str:find(fpat, last_end)
if limit ~= nil and limit <= #t then
break
end
end
if last_end <= #str then
cap = str:sub(last_end)
table.insert(t, cap)
end
return t
end
Se você programa em Lua, está sem sorte aqui. Lua é A única linguagem de programação que é notoriamente infame porque seus autores nunca implementaram "a" função de divisão na biblioteca padrão e, em vez disso, escreveram 16 tela cheia de explicações e desculpas esfarrapadas de por que eles não fizeram e não o fizeram, intercalado com vários exemplos de semi-trabalho que são praticamente garantidos para trabalhar para quase todos, exceto na sua área de trabalho . Este é apenas o estado da arte de Lua, e todo mundo que programa em Lua simplesmente acaba cerrando os dentes e iterando sobre os personagens. Existem muitas soluções existentes às vezes melhores, mas exatamente zero soluções confiáveis .