204 votes

Diviser une chaîne en Lua ?

Je dois faire une simple division d'une chaîne de caractères, 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?

3 votes

16voto

Norman Ramsey Points 115730

Tout comme string.gmatch trouvera 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..")")
  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

Par défaut, cela renvoie ce qui est séparé par des espaces.

7 votes

+1. Note à tout autre débutant 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, j'ai dû essayer pour comprendre ces choses.)

15voto

Faisal Hanif Points 61

Voici la fonction :

function split(pString, pPattern)
   local Table = {}  -- NOTER : utiliser {n = 0} en 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

Appellez-le comme suit :

list=split(string_to_split,pattern_to_match)

par exemple :

list=split("1:2:3:4","\:")

Pour en savoir plus, allez ici:
http://lua-users.org/wiki/SplitJoin

10voto

Diego Pino Points 2849

Parce qu'il y a plusieurs façons de tuer 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)

Output: 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 récupère toutes les chaînes qui correspondent à regex. Le regex prend tous les caractères jusqu'à trouver un séparateur.

9voto

Jack Taylor Points 2090

Beaucoup de ces réponses n'acceptent que des séparateurs d'un seul caractère, ou ne gèrent pas bien les cas limites (par exemple, des séparateurs vides), c'est pourquoi j'ai pensé fournir une solution plus définitive.

Voici deux fonctions, gsplit et split, adaptées du code de l'extension Scribunto MediaWiki, qui est utilisée sur des wikis comme Wikipédia. 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 compréhensible, et j'ai également modifié le code pour utiliser des motifs de chaînes de caractères Lua régulières au lieu des motifs de Scribunto pour les chaînes de caractères Unicode. Le code original comporte des cas de test ici.

-- gsplit: itérer sur des sous-chaînes dans une chaîne séparées par un motif
-- 
-- Paramètres:
-- text (string)    - la chaîne sur laquelle itérer
-- pattern (string) - le motif de séparation
-- plain (booléen)  - si vrai (ou vrai), le motif est interprété comme une
--                    chaîne simple, pas un motif Lua
-- 
-- Renvoie : itérateur
--
-- Utilisation :
-- pour souschaine in gsplit(text, motif, simple) faire
--   faireQuelqueChose(souschaine)
-- fin
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
        -- Séparateur vide !
        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: diviser une chaîne en sous-chaînes séparées par un motif.
-- 
-- Paramètres:
-- text (string)    - la chaîne sur laquelle itérer
-- pattern (string) - le motif de séparation
-- plain (booléen)  - si vrai (ou vrai), le motif est interprété comme une
--                    chaîne simple, pas un motif Lua
-- 
-- Renvoie : table (une table de séquence contenant les sous-chaînes)
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 l'utilisation de la fonction split :

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

7voto

Ivo Beckers Points 1023

J'aime cette solution courte

fonction split(s, délimiteur)
    résultat = {};
    pour correspondance dans (s..délimiteur):gmatch("(.-)"..délimiteur) faire
        table.insert(résultat, correspondance);
    fin
    retourner résultat;
fin

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X