Stringa divisa in Lua?


Answers

Ecco la mia soluzione davvero semplice. Utilizzare la funzione gmatch per acquisire stringhe che contengono almeno UN carattere di QUALSIASI diverso dal separatore desiderato. Il separatore è QUALSIASI spazio bianco (% s in Lua) per impostazione predefinita:

function mysplit(inputstr, sep)
        if sep == nil then
                sep = "%s"
        end
        local t={} ; i=1
        for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
                t[i] = str
                i = i + 1
        end
        return t
end
Question

Ho bisogno di fare una semplice divisione di una stringa, ma non sembra esserci una funzione per questo, e il modo manuale che ho testato non sembra funzionare. Come lo farei?




Perché ci sono più di un modo per scuoiare un gatto, ecco il mio approccio:

Codice :

#!/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

Risultato : 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. 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.

Spiegazione :

La funzione gmatch funziona come un iteratore, recupera tutte le stringhe che corrispondono alla regex . L' regex accetta tutti i caratteri finché non trova un separatore.




Molte di queste risposte accettano solo separatori a carattere singolo, o non gestiscono bene i casi limite (es. Separatori vuoti), quindi ho pensato di fornire una soluzione più definitiva.

Ecco due funzioni, gsplit e split , adattate dal code nell'estensione di Scribunto MediaWiki , che viene utilizzata su wiki come Wikipedia. Il codice è concesso in licenza sotto GPL v2 . Ho cambiato i nomi delle variabili e ho aggiunto dei commenti per rendere il codice un po 'più facile da capire, e ho anche cambiato il codice per usare normali schemi di stringhe Lua al posto dei pattern di Scribunto per le stringhe Unicode. Il codice originale ha here casi di test.

-- 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

Alcuni esempi della funzione split in uso:

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



Ho usato gli esempi di cui sopra per creare la mia funzione. Ma il pezzo mancante per me era automaticamente sfuggire a personaggi magici.

Ecco il mio contributo:

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



Ecco la funzione:

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

Chiamalo come:

list=split(string_to_split,pattern_to_match)

per esempio:

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


Per ulteriori informazioni vai qui:
http://lua-users.org/wiki/SplitJoin




Se vuoi solo scorrere i token, questo è abbastanza bello:

line = "one, two and 3!"

for token in string.gmatch(line, "[^%s]+") do
   print(token)
end

Produzione:

uno,

Due

e

3!

Breve spiegazione: il pattern "[^% s] +" corrisponde a ogni stringa non vuota tra i caratteri dello spazio.