J'ai besoin de faire une simple division d'une chaîne, mais il ne semble pas y avoir de fonction pour cela, et la méthode manuelle que j'ai testée ne semble pas fonctionner. Comment pourrais-je le faire?
Voici ma solution très simple. Utilisez la fonction gmatch pour capturer des chaînes contenant au moins UN caractère de ANALYSE autre que le séparateur souhaité. Le séparateur est TOUT ESPACE (% s en Lua) par défaut:
function mysplit (inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={}
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
table.insert(t, inputstr)
end
return t
end
Si vous divisez une chaîne en Lua, vous devriez essayer les méthodes string.gmatch () ou string.sub (). Utilisez la méthode string.sub () si vous connaissez l'index sur lequel vous souhaitez scinder la chaîne, ou utilisez string.gmatch () si vous souhaitez analyser la chaîne pour rechercher l'emplacement où diviser la chaîne.
Exemple utilisant string.gmatch () de Manuel de référence de Lua 5.1 :
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Si vous voulez juste parcourir les jetons, c'est très joli:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Sortie:
un,
deux
et
3!
Explication brève: le modèle "[^% s] +" correspond à chaque chaîne non vide située entre les espaces.
Tout comme string.gmatch
trouvera patterns dans une chaîne, cette fonction trouvera les choses entre patterns:
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
Par défaut, il retourne tout ce qui est séparé par des espaces.
Voici la fonction:
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
Appelez ça comme:
list=split(string_to_split,pattern_to_match)
par exemple.:
list=split("1:2:3:4","\:")
Pour plus, allez ici:
http://lua-users.org/wiki/SplitJoin
J'aime cette courte solution
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
Parce qu'il y a plus d'une façon de peler un chat, voici mon approche:
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
Sortie: 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.
Explication:
La fonction gmatch
fonctionne comme un itérateur, elle extrait toutes les chaînes qui correspondent à regex
. La regex
prend tous les caractères jusqu'à trouver un séparateur.
Vous pouvez utiliser cette méthode:
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)
Simplement assis sur un délimiteur
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
Un grand nombre de ces réponses n'acceptent que les séparateurs à un caractère ou ne traitent pas bien les cas Edge (séparateurs vides, par exemple). J'ai donc pensé proposer une solution plus définitive.
Voici deux fonctions, gsplit
et split
, adaptées du code dans le extension Scribunto MediaWiki , qui est utilisé sur des wikis tels que Wikipedia. Le code est sous licence GPL v2 . J'ai changé les noms des variables et ajouté des commentaires pour rendre le code un peu plus facile à comprendre. J'ai également modifié le code pour qu'il utilise des modèles de chaînes Lua classiques au lieu des modèles de Scribunto pour les chaînes Unicode. Le code original a des tests élémentaires ici .
-- 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
Quelques exemples de la fonction split
utilisée:
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
une voie qu'on ne voit pas chez les autres
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
J'ai utilisé les exemples ci-dessus pour créer ma propre fonction. Mais la pièce manquante pour moi échappait automatiquement aux personnages magiques.
Voici ma contribution:
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
Vous pouvez utiliser bibliothèque de penlight . Cela a une fonction pour diviser une chaîne en utilisant un délimiteur qui affiche la liste.
Il a mis en œuvre de nombreuses fonctions dont nous pourrions avoir besoin lors de la programmation et manquantes dans Lua.
Voici l'exemple pour l'utiliser.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
Selon le cas d'utilisation, cela pourrait être utile. Il coupe tout le texte de chaque côté des drapeaux:
b = "This is a string used for testing"
--Removes unwanted text
c = (b:match("a([^/]+)used"))
print (c)
Sortie:
string