J'ai besoin de faire un simple fractionnement 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 le ferais-je?
Voici ma solution vraiment simple. Utiliser la fonction de gmatch à des chaînes de capture qui contiennent au moins un caractère de quoi que ce soit autre que le séparateur désiré. Le séparateur est ** n'importe quel * espace (% s en Lua) par défaut:
function mysplit (inputstr, sep)if sep ==nilthen
sep ="%s"endlocal t={}for str in string.gmatch(inputstr,"([^"..sep.."]+)")do
table.insert(t, str)endreturn t
end
Wow, la première réponse à toute cette question qui a en fait une fonction qui renvoie une table. Notez cependant que t et moi avons besoin du modificateur "local", car vous écrasez les globaux. :)
cib
3
Comme d'autres l'ont souligné, vous pouvez simplifier cela en utilisant table.insert (t, str) au lieu de t [i] = str et alors vous n'avez pas besoin de i = 1 ou i = i +1
James Newton
2
Ne fonctionne pas si la chaîne contient des valeurs vides, par exemple. 'foo,,bar'. Vous obtenez {'foo','bar'}au lieu de{'foo', '', 'bar'}
andras
5
C'est vrai. La prochaine version fonctionnera dans ce cas: 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
bart
33
Si vous divisez une chaîne dans Lua, vous devriez essayer les méthodes string.gmatch () ou string.sub (). Utilisez la méthode string.sub () si vous connaissez l'index dans lequel vous souhaitez diviser la chaîne, ou utilisez la chaîne string.gmatch () si vous analyserez la chaîne pour trouver l'emplacement à partir duquel diviser la chaîne.
Le modèle %Sest égal à celui que vous avez mentionné, tout comme %Sla négation de %s, comme l' %Dest la négation de %d. De plus, %west égal à [A-Za-z0-9_](d'autres caractères peuvent être pris en charge en fonction de vos paramètres régionaux).
Lars Gyrup Brink Nielsen
14
Tout comme string.gmatchtrouvera des motifs dans une chaîne, cette fonction trouvera les choses entre les motifs:
function string:split(pat)
pat = pat or'%s+'local st, g =1, self:gmatch("()("..pat..")")localfunction getter(segs, seps, sep, cap1,...)
st = sep and seps +#sep
return self:sub(segs,(seps or0)-1), cap1 or sep,...endreturnfunction()if st thenreturn getter(st, g())endendend
Par défaut, il renvoie tout ce qui est séparé par des espaces.
+1. Note à tous les autres débutants de Lua: cela renvoie un itérateur, et «entre les motifs» inclut le début et la fin de la chaîne. (En tant que débutant, je devais l'essayer pour comprendre ces choses.)
Darius Bacon
12
Voici la fonction:
function split(pString, pPattern)local Table ={}-- NOTE: use {n = 0} in Lua-5.0local fpat ="(.-)".. pPattern
local last_end =1local s, e, cap = pString:find(fpat,1)while s doif s ~=1or cap ~=""then
table.insert(Table,cap)end
last_end = e+1
s, e, cap = pString:find(fpat, last_end)endif last_end <=#pString then
cap = pString:sub(last_end)
table.insert(Table, cap)endreturn Table
end
C'est mon préféré, car il est si court et simple. Je ne comprends pas très bien ce qui se passe, quelqu'un pourrait-il m'expliquer?
hexagonest
2
Cela échoue lors de l'utilisation du point comme délimiteur (ou potentiellement tout autre caractère magique de motif)
TurboHz
6
Parce qu'il y a plus d'une façon d'écorcher 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.
]=]localfunction split(str, sep)local result ={}local regex =("([^%s]+)"):format(sep)for each in str:gmatch(regex)do
table.insert(result, each)endreturn result
endlocal 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 gmatchfonction fonctionne comme un itérateur, elle récupère toutes les chaînes qui correspondent regex. Le regexprend tous les caractères jusqu'à ce qu'il trouve un séparateur.
function string:split(delimiter)local result ={}local from =1local 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)
Beaucoup de ces réponses n'acceptent que les séparateurs à un seul caractère, ou ne traitent pas bien les cas de bord (par exemple, les séparateurs vides), j'ai donc pensé que je fournirais une solution plus définitive.
Voici deux fonctions, gsplitet split, adaptées du code dans le extension Scribunto MediaWiki , qui est utilisée sur des wikis comme 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, et j'ai également changé le code pour utiliser des modèles de chaînes Lua réguliers au lieu des modèles de Scribunto pour les chaînes Unicode. Le code d'origine a des cas de test 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)-- endlocalfunction gsplit(text, pattern, plain)local splitStart, length =1,#text
returnfunction()if splitStart thenlocal sepStart, sepEnd = string.find(text, pattern, splitStart, plain)local ret
ifnot sepStart then
ret = string.sub(text, splitStart)
splitStart =nilelseif sepEnd < sepStart then-- Empty separator!
ret = string.sub(text, splitStart, sepStart)if sepStart < length then
splitStart = sepStart +1else
splitStart =nilendelse
ret = sepStart > splitStart and string.sub(text, splitStart, sepStart -1)or''
splitStart = sepEnd +1endreturn ret
endendend-- 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)localfunction split(text, pattern, plain)local ret ={}for match in gsplit(text, pattern, plain)do
table.insert(ret, match)endreturn ret
end
Quelques exemples de la splitfonction utilisée:
localfunction 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
function str_split(str, sep)if sep ==nilthen
sep ='%s'endlocal 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 était d'échapper 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 ==nilthen
delim ="%s"elseif string.find(delim, magic,1,true)then-- escape magic
delim ="%"..delim
endlocal pattern ="[^"..delim.."]+"for w in string.gmatch(text, pattern)do
table.insert(result, w)endreturn result
end
Super tard à cette question, mais au cas où quelqu'un voudrait une version qui gère le nombre de fractionnements que vous souhaitez obtenir .....
-- 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 =1local s, e, cap = str:find(fpat,1)while s doif s ~=1or cap ~=""then
table.insert(t, cap)end
last_end = e+1
s, e, cap = str:find(fpat, last_end)if limit ~=niland limit <=#t thenbreakendendif last_end <=#str then
cap = str:sub(last_end)
table.insert(t, cap)endreturn t
end
Si vous programmez en Lua, vous n'avez pas de chance ici. Lua est LE langage de programmation qui se trouve être notoirement tristement célèbre parce que ses auteurs n'ont jamais implémenté "la" fonction de fractionnement dans la bibliothèque standard, et ont plutôt écrit 16 écrans pleins d'explications et d'excuses boiteuses pour expliquer pourquoi ils ne l'ont pas fait et ne le seraient pas, entrecoupé de nombreux exemples à moitié fonctionnels qui sont pratiquement garantis de fonctionner pour presque tout le monde mais qui se cassent dans votre cas du coin. C'est juste l'état de l'art de Lua, et tous ceux qui programment en Lua finissent simplement par serrer les dents et itérer sur les personnages. Il existe de nombreuses solutions qui sont parfois meilleures, mais exactement aucune solution qui est sûrement meilleure.
Réponses:
Voici ma solution vraiment simple. Utiliser la fonction de gmatch à des chaînes de capture qui contiennent au moins un caractère de quoi que ce soit autre que le séparateur désiré. Le séparateur est ** n'importe quel * espace (% s en Lua) par défaut:
.
la source
'foo,,bar'
. Vous obtenez{'foo','bar'}
au lieu de{'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
Si vous divisez une chaîne dans Lua, vous devriez essayer les méthodes string.gmatch () ou string.sub (). Utilisez la méthode string.sub () si vous connaissez l'index dans lequel vous souhaitez diviser la chaîne, ou utilisez la chaîne string.gmatch () si vous analyserez la chaîne pour trouver l'emplacement à partir duquel diviser la chaîne.
Exemple utilisant string.gmatch () du manuel de référence de Lua 5.1 :
la source
Si vous souhaitez simplement parcourir les jetons, c'est plutôt chouette:
Production:
Brève explication: le motif "[^% s] +" correspond à toutes les chaînes non vides entre les espaces.
la source
%S
est égal à celui que vous avez mentionné, tout comme%S
la négation de%s
, comme l'%D
est la négation de%d
. De plus,%w
est égal à[A-Za-z0-9_]
(d'autres caractères peuvent être pris en charge en fonction de vos paramètres régionaux).Tout comme
string.gmatch
trouvera des motifs dans une chaîne, cette fonction trouvera les choses entre les motifs:Par défaut, il renvoie tout ce qui est séparé par des espaces.
la source
Voici la fonction:
Appelez ça comme:
par exemple:
Pour en savoir plus, rendez-vous ici:
http://lua-users.org/wiki/SplitJoin
la source
J'aime cette solution courte
la source
Parce qu'il y a plus d'une façon d'écorcher un chat, voici mon approche:
Code :
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
gmatch
fonction fonctionne comme un itérateur, elle récupère toutes les chaînes qui correspondentregex
. Leregex
prend tous les caractères jusqu'à ce qu'il trouve un séparateur.la source
Vous pouvez utiliser cette méthode:
la source
Beaucoup de ces réponses n'acceptent que les séparateurs à un seul caractère, ou ne traitent pas bien les cas de bord (par exemple, les séparateurs vides), j'ai donc pensé que je fournirais une solution plus définitive.
Voici deux fonctions,
gsplit
etsplit
, adaptées du code dans le extension Scribunto MediaWiki , qui est utilisée sur des wikis comme 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, et j'ai également changé le code pour utiliser des modèles de chaînes Lua réguliers au lieu des modèles de Scribunto pour les chaînes Unicode. Le code d'origine a des cas de test ici .Quelques exemples de la
split
fonction utilisée:la source
une voie que l'on ne voit pas chez les autres
la source
Assis simplement sur un délimiteur
la source
J'ai utilisé les exemples ci-dessus pour créer ma propre fonction. Mais la pièce manquante pour moi était d'échapper automatiquement aux personnages magiques.
Voici ma contribution:
la source
Vous pouvez utiliser la bibliothèque penlight . Cela a une fonction pour diviser la chaîne en utilisant un délimiteur qui génère une liste.
Il a implémenté de nombreuses fonctions dont nous pourrions avoir besoin lors de la programmation et manquantes dans Lua.
Voici l'exemple pour l'utiliser.
la source
Selon le cas d'utilisation, cela peut être utile. Il coupe tout le texte de chaque côté des drapeaux:
Production:
la source
Super tard à cette question, mais au cas où quelqu'un voudrait une version qui gère le nombre de fractionnements que vous souhaitez obtenir .....
la source
Si vous programmez en Lua, vous n'avez pas de chance ici. Lua est LE langage de programmation qui se trouve être notoirement tristement célèbre parce que ses auteurs n'ont jamais implémenté "la" fonction de fractionnement dans la bibliothèque standard, et ont plutôt écrit 16 écrans pleins d'explications et d'excuses boiteuses pour expliquer pourquoi ils ne l'ont pas fait et ne le seraient pas, entrecoupé de nombreux exemples à moitié fonctionnels qui sont pratiquement garantis de fonctionner pour presque tout le monde mais qui se cassent dans votre cas du coin. C'est juste l'état de l'art de Lua, et tous ceux qui programment en Lua finissent simplement par serrer les dents et itérer sur les personnages. Il existe de nombreuses solutions qui sont parfois meilleures, mais exactement aucune solution qui est sûrement meilleure.
la source