Antworten:
Hier ist meine wirklich einfache Lösung. Verwenden Sie die Funktion gmatch, um Zeichenfolgen zu erfassen, die mindestens ein Zeichen von etwas anderem als dem gewünschten Trennzeichen enthalten. Das Trennzeichen ist standardmäßig ** ein beliebiges * Leerzeichen (% s in 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'
. Sie erhalten {'foo','bar'}
statt{'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
Wenn Sie eine Zeichenfolge in Lua aufteilen, sollten Sie die Methoden string.gmatch () oder string.sub () ausprobieren. Verwenden Sie die Methode string.sub (), wenn Sie den Index kennen, bei dem Sie die Zeichenfolge teilen möchten, oder verwenden Sie string.gmatch (), wenn Sie die Zeichenfolge analysieren, um die Position zu finden, an der die Zeichenfolge aufgeteilt werden soll.
Beispiel mit string.gmatch () von Lua 5.1 Referenzhandbuch :
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Wenn Sie nur über die Token iterieren möchten, ist dies ziemlich ordentlich:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Ausgabe:
einer,
zwei
und
3!
Kurze Erklärung: Das Muster "[^% s] +" stimmt mit jeder nicht leeren Zeichenfolge zwischen Leerzeichen überein.
%S
ist gleich dem, das Sie erwähnt haben, ebenso %S
wie die Negation von %s
, ebenso wie %D
die Negation von %d
. Ist außerdem %w
gleich [A-Za-z0-9_]
(je nach Gebietsschema werden möglicherweise andere Zeichen unterstützt).
So wie string.gmatch
findet Muster in einem String, wird diese Funktion , um die Dinge finden zwischen Mustern:
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
Standardmäßig wird alles zurückgegeben, was durch Leerzeichen getrennt ist.
Hier ist die Funktion:
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
Nennen Sie es wie:
list=split(string_to_split,pattern_to_match)
z.B:
list=split("1:2:3:4","\:")
Weitere Informationen finden Sie hier:
http://lua-users.org/wiki/SplitJoin
Ich mag diese kurze Lösung
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
Da es mehr als einen Weg gibt, eine Katze zu häuten, ist hier mein Ansatz:
Code :
#!/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
Ausgabe :
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.
Erklärung :
Die gmatch
Funktion arbeitet als Iterator und ruft alle übereinstimmenden Zeichenfolgen ab regex
. Das regex
nimmt alle Zeichen, bis es ein Trennzeichen findet.
Sie können diese Methode verwenden:
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)
Viele dieser Antworten akzeptieren nur Trennzeichen mit einem Zeichen oder behandeln Randfälle nicht gut (z. B. leere Trennzeichen), daher dachte ich, ich würde eine endgültigere Lösung anbieten.
Hier sind zwei Funktionen, gsplit
und split
aus dem Code in der angepasst Scribunto MediaWiki - Erweiterung , die auf Wikis wie Wikipedia verwendet wird. Der Code ist unter der GPL v2 lizenziert . Ich habe die Variablennamen geändert und Kommentare hinzugefügt, um den Code ein wenig verständlicher zu machen, und ich habe den Code so geändert, dass anstelle von Scribuntos Mustern für Unicode-Zeichenfolgen reguläre Lua-Zeichenfolgenmuster verwendet werden. Der ursprüngliche Code hat Testfälle hier .
-- 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
Einige Beispiele für die verwendete split
Funktion:
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
Einfach auf einem Begrenzer sitzen
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
Ich habe die obigen Beispiele verwendet, um meine eigene Funktion zu erstellen. Aber das fehlende Stück für mich entkam automatisch magischen Charakteren.
Hier ist mein Beitrag:
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
Sie könnten die Taschenlampenbibliothek verwenden . Dies hat eine Funktion zum Teilen von Zeichenfolgen mithilfe eines Trennzeichens, das eine Liste ausgibt.
Es hat viele der Funktionen implementiert, die wir möglicherweise beim Programmieren benötigen und die in Lua fehlen.
Hier ist das Beispiel für die Verwendung.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
Super spät zu dieser Frage, aber für den Fall, dass jemand eine Version möchte, die die Anzahl der Splits verarbeitet, die Sie erhalten möchten .....
-- 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
Wenn Sie in Lua programmieren, haben Sie hier kein Glück. Lua ist DIE einzige Programmiersprache, die notorisch berüchtigt ist, weil ihre Autoren "die" Split-Funktion nie in der Standardbibliothek implementiert haben und stattdessen 16 Bildschirme mit Erklärungen und lahmen Ausreden geschrieben haben, warum sie es nicht taten und nicht taten. durchsetzt mit zahlreichen halbarbeitenden Beispielen, die praktisch für fast jeden funktionieren, aber in Ihrem Eckkoffer brechen . Dies ist nur der Stand der Technik bei Lua, und jeder, der in Lua programmiert, beißt einfach die Zähne zusammen und iteriert über Charaktere. Es gibt viele Lösungen, die manchmal besser sind, aber genau null Lösungen, die zuverlässig besser sind.