¿Separar una cuerda en Lua?

Necesito hacer una simple división de una cadena, pero no parece haber una función para esto, y la forma manual que probé no pareció funcionar. ¿Cómo lo haría?

Por favor, lea Splitting Strings :

Aquí hay varias formas de dividir una cadena en una lista de subcadenas, rompiendo la cadena original en las ocurrencias de algún separador (carácter, juego de caracteres o patrón). Esto se conoce comúnmente como una función de división de cuerdas [2].

Aquí está mi solución realmente simple. Use la función de coincidencia para capturar cadenas que contengan al menos UN carácter de CUALQUIER COSA que no sea el separador deseado. El separador es CUALQUIER espacio en blanco (% s en Lua) por defecto:

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 

Si está dividiendo una cadena en Lua, debe probar los métodos string.gmatch () o string.sub (). Utilice el método string.sub () si conoce el índice en el que desea dividir la cadena, o use el string.gmatch () si analizará la cadena para encontrar la ubicación donde dividir la cadena.

Ejemplo usando string.gmatch () de Lua 5.1 Manual de referencia :

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

Si solo quieres iterar sobre los tokens, esto es bastante claro:

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

Salida:

uno,

dos

y

3!

Breve explicación: el patrón “[^% s] +” coincide con cada cadena no vacía entre los caracteres espaciales.

Así como string.gmatch encontrará patrones en una cadena, esta función encontrará las cosas entre patrones:

 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 defecto, devuelve lo que está separado por espacios en blanco.

Aquí está la función:

 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 

Llámalo así:

 list=split(string_to_split,pattern_to_match) 

p.ej:

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

Para más ir aquí:
http://lua-users.org/wiki/SplitJoin

Me gusta esta solución corta

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

Debido a que hay más de una manera de despellejar a un gato, este es mi enfoque:

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 

Salida : 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.

Explicación

La función gmatch funciona como un iterador, recupera todas las cadenas que coinciden con regex . La regex toma todos los caracteres hasta que encuentra un separador.

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

Simplemente sentado en un delimitador

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

Usé los ejemplos anteriores para crear mi propia función. Pero la pieza que faltaba para mí escapaba automáticamente de los personajes mágicos.

Aquí está mi contribución:

 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 

Muchas de estas respuestas solo aceptan separadores de un solo carácter, o no se ocupan bien de los bordes (p. Ej., Separadores vacíos), así que pensé en proporcionar una solución más definitiva.

Aquí hay dos funciones, gsplit y split , adaptadas del código en la extensión Scribunto MediaWiki , que se usa en wikis como Wikipedia. El código está licenciado bajo GPL v2 . Cambié los nombres de las variables y agregué los comentarios para hacer que el código sea un poco más fácil de entender, y también he cambiado el código para usar patrones regulares de Lua en lugar de los patrones de Scribunto para cadenas Unicode. El código original tiene casos de prueba aquí .

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

Algunos ejemplos de la función split en 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 

una forma que no se ve en los demás

 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