Risposte:
Ecco la mia soluzione davvero semplice. Utilizzare la funzione gmatch per acquisire stringhe che contengono almeno un carattere di qualsiasi cosa diversa dal separatore desiderato. Il separatore è ** qualsiasi * spazio bianco (% s in Lua) per impostazione predefinita:
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'
. Si ottiene {'foo','bar'}
, invece di{'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 stai dividendo una stringa in Lua, dovresti provare i metodi string.gmatch () o string.sub (). Utilizzare il metodo string.sub () se si conosce l'indice in cui si desidera dividere la stringa oppure utilizzare string.gmatch () se si analizzerà la stringa per trovare la posizione in cui dividere la stringa.
Esempio usando string.gmatch () dal Manuale di riferimento di Lua 5.1 :
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Se vuoi semplicemente scorrere i token, questo è abbastanza pulito:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Produzione:
uno,
Due
e
3!
Breve spiegazione: il modello "[^% s] +" corrisponde a ogni stringa non vuota tra caratteri spaziali.
%S
è uguale a quello che hai menzionato, come %S
è la negazione di %s
, come %D
è la negazione di %d
. Inoltre, %w
è uguale a [A-Za-z0-9_]
(altri caratteri potrebbero essere supportati a seconda delle impostazioni internazionali).
Proprio come string.gmatch
troverà i pattern in una stringa, questa funzione troverà le cose tra i pattern:
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
Di default restituisce tutto ciò che è separato da spazi bianchi.
Ecco la funzione:
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
Chiamalo come:
list=split(string_to_split,pattern_to_match)
per esempio:
list=split("1:2:3:4","\:")
Per di più vai qui:
http://lua-users.org/wiki/SplitJoin
Mi piace questa soluzione breve
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
Perché ci sono più di un modo per scuoiare un gatto, ecco il mio approccio:
Codice :
#!/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
Uscita :
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.
Spiegazione :
La gmatch
funzione funziona come iteratore, recupera tutte le stringhe corrispondenti regex
. La regex
prende tutti i caratteri fino a quando trova un separatore.
Puoi usare questo metodo:
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)
Molte di queste risposte accettano solo separatori a carattere singolo o non trattano bene i casi limite (ad es. Separatori vuoti), quindi ho pensato di fornire una soluzione più definitiva.
Qui sono due funzioni, gsplit
e split
, adattato dal codice nella estensione Scribunto MediaWiki , che è usato su wiki come Wikipedia. Il codice è concesso in licenza in base alla GPL v2 . Ho cambiato i nomi delle variabili e aggiunto commenti per rendere il codice un po 'più semplice da capire, e ho anche cambiato il codice per usare i normali schemi di stringa Lua invece dei modelli di Scribunto per le stringhe Unicode. Il codice originale contiene casi di test qui .
-- 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
Alcuni esempi della split
funzione in 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
Semplicemente seduto su un delimitatore
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
Ho usato gli esempi sopra per creare la mia funzione. Ma il pezzo mancante per me stava automaticamente sfuggendo ai personaggi magici.
Ecco il mio contributo:
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
È possibile utilizzare la libreria penlight . Questo ha una funzione per dividere la stringa usando il delimitatore che restituisce l'elenco.
Ha implementato molte delle funzioni di cui potremmo avere bisogno durante la programmazione e la mancanza in Lua.
Ecco l'esempio per usarlo.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
Super in ritardo a questa domanda, ma nel caso qualcuno voglia una versione che gestisca la quantità di divisioni che vuoi ottenere .....
-- 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 programmi a Lua, sei sfortunato qui. Lua è L'unico linguaggio di programmazione che è notoriamente famigerato perché i suoi autori non hanno mai implementato "la" funzione divisa nella libreria standard, e invece hanno scritto 16 schermate di spiegazioni e scuse scuse sul perché non lo facessero e non lo avrebbero fatto, intervallati da numerosi esempi a metà lavoro che sono virtualmente garantito il funzionamento per quasi tutti, ma pausa nel vostro caso d'angolo. Questo è solo lo stato dell'arte di Lua e tutti coloro che programmano in Lua finiscono semplicemente per stringere i denti e iterare sui personaggi. Esistono molte soluzioni che a volte sono migliori, ma esattamente zero soluzioni che sono attendibilmente migliori.