Odpowiedzi:
Oto moje naprawdę proste rozwiązanie. Użyj funkcji gmatch, aby przechwycić ciągi zawierające co najmniej jeden znak lub dowolny inny znak niż żądany separator. Separatorem jest domyślnie ** dowolna * biała spacja (% s w 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
.
'foo,,bar'
. Dostajesz {'foo','bar'}
zamiast{'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
Jeśli dzielisz łańcuch w Lua, powinieneś wypróbować metody string.gmatch () lub string.sub (). Użyj metody string.sub (), jeśli znasz indeks, w którym chcesz podzielić ciąg, lub użyj string.gmatch (), jeśli przeanalizujesz ciąg w celu znalezienia lokalizacji, w której chcesz podzielić ciąg.
Przykład użycia string.gmatch () z 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
Jeśli chcesz tylko iterować po tokenach, jest to całkiem fajne:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Wynik:
jeden,
dwa
i
3!
Krótkie wyjaśnienie: wzorzec „[^% s] +” pasuje do każdego niepustego ciągu między znakami spacji.
%S
jest równy temu, o którym wspomniałeś, podobnie jak %S
negacja %s
, podobnie jak %D
negacja %d
. Dodatkowo %w
jest równe [A-Za-z0-9_]
(inne znaki mogą być obsługiwane w zależności od ustawień regionalnych).
Podobnie jak w string.gmatch
przypadku wyszukiwania wzorców w ciągu, ta funkcja znajdzie rzeczy między wzorami:
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
Domyślnie zwraca wszystko, co jest oddzielone białymi znakami.
Oto funkcja:
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
Nazwij to tak:
list=split(string_to_split,pattern_to_match)
na przykład:
list=split("1:2:3:4","\:")
Więcej informacji można znaleźć tutaj:
http://lua-users.org/wiki/SplitJoin
Podoba mi się to krótkie rozwiązanie
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
Ponieważ istnieje więcej niż jeden sposób oskórowania kota, oto moje podejście:
Kod :
#!/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
Wyjście :
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.
Wyjaśnienie :
Te gmatch
prace funkcjonowała jako iterator, to pobiera wszystkie sznurki pasujących regex
. regex
Wykonuje wszystkie znaki aż znajdzie separator.
Możesz użyć tej metody:
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)
Wiele z tych odpowiedzi akceptuje tylko separatory jednoznakowe lub nie radzi sobie dobrze z przypadkami brzegowymi (np. Puste separatory), więc pomyślałem, że zapewnię bardziej ostateczne rozwiązanie.
Oto dwie funkcje gsplit
i split
, zaadaptowane z kodu w rozszerzeniu Scribunto MediaWiki , które jest używane na stronach wiki, takich jak Wikipedia. Kod jest objęty licencją GPL v2 . Zmieniłem nazwy zmiennych i dodałem komentarze, aby kod był nieco łatwiejszy do zrozumienia, a także zmieniłem kod tak, aby używał zwykłych wzorców ciągów Lua zamiast wzorców Scribunto dla ciągów Unicode. Oryginalny kod zawiera tutaj przypadki testowe .
-- 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
Kilka przykładów split
używanej funkcji:
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
Po prostu siedząc na ograniczniku
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
Wykorzystałem powyższe przykłady do stworzenia własnej funkcji. Ale brakującym dla mnie elementem automatycznie wymykał się magicznym postaciom.
Oto mój wkład:
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
Możesz użyć biblioteki Penlight . Ma funkcję dzielenia łańcucha za pomocą separatora, który wyświetla listę.
Zaimplementował wiele funkcji, których możemy potrzebować podczas programowania i których brakuje w Lua.
Oto przykład użycia go.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
Bardzo późno na to pytanie, ale na wypadek, gdyby ktoś chciał mieć wersję obsługującą liczbę podziałów, które chcesz uzyskać .....
-- 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
Jeśli programujesz w Lua, nie masz tu szczęścia. Lua jest JEDYNYM językiem programowania, który tak się składa, że jest notorycznie niesławny, ponieważ jego autorzy nigdy nie zaimplementowali funkcji podziału w bibliotece standardowej, a zamiast tego napisali 16 ekranów pełnych wyjaśnień i kiepskich wymówek, dlaczego tego nie zrobili, a czego nie, przeplatane licznymi półpracującymi przykładami, które praktycznie gwarantują pracę dla prawie wszystkich, ale nie sprawdzają się w Twojej narożnej sprawie. To jest po prostu najnowocześniejszy Lua, a wszyscy, którzy programują w Lua, po prostu zaciskają zęby i powtarzają postacie. Istnieje wiele rozwiązań, które czasami są lepsze, ale dokładnie zero rozwiązań, które są niezawodnie lepsze.