Lua dize bölünmüş?


160

Ben bir dize basit bir bölünme yapmak gerekir, ama bunun için bir fonksiyon gibi görünmüyor ve test manuel şekilde işe yaramadı gibi görünüyordu. Bunu nasıl yaparım?


Yanıtlar:


96

İşte benim gerçekten basit çözümüm. İstenen ayırıcıdan başka herhangi bir şeyin en az bir karakterini içeren dizeleri yakalamak için gmatch işlevini kullanın . Ayırıcı varsayılan olarak ** herhangi bir * boşluktur (Lua'da% s):

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

.


1
Teşekkürler. Tam aradığım şey.
Nicholas

3
Vay canına, bu sorunun tamamında bir tablo döndüren bir işlevi olan ilk cevap. Yine de, bu t ve ben "yerel" değiştirici gerekir, çünkü küresel üzerine yazıyoruz. :)
cib

3
Diğerlerinin de belirttiği gibi, t ​​[i] = str yerine table.insert (t, str) kullanarak bunu basitleştirebilirsiniz ve sonra i = 1 veya i = i +1'ye ihtiyacınız yoktur
James Newton

2
Dize boş değerler içeriyorsa çalışmaz, örn. 'foo,,bar'. Sen almak {'foo','bar'}yerine{'foo', '', 'bar'}
kiscica

5
Doğru. Bir sonraki sürüm bu durumda çalışacaktır: 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

Bir dizeyi Lua'da bölüyorsanız, string.gmatch () veya string.sub () yöntemlerini denemelisiniz. Dizeyi bölmek istediğiniz dizini biliyorsanız string.sub () yöntemini kullanın veya dizenin bölüneceği konumu bulmak için dizeyi ayrıştırırsanız string.gmatch () yöntemini kullanın.

Lua 5.1 Başvuru Kılavuzu'ndan string.gmatch () kullanılan örnek :

 t = {}
 s = "from=world, to=Lua"
 for k, v in string.gmatch(s, "(%w+)=(%w+)") do
   t[k] = v
 end

Zaten bu lua kullanıcıların sayfa sayesinde bir uygulama "ödünç"
RCIX

24

Sadece jetonları tekrarlamak istiyorsanız, bu oldukça düzgün:

line = "one, two and 3!"

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

Çıktı:

bir,

iki

ve

3!

Kısa açıklama: "[^% s] +" deseni, boşluk karakterleri arasındaki boş olmayan her dizeyle eşleşir.


2
Desen %Solarak, Bahsettiğiniz birine eşittir %Solumsuzlanmasıdır %sgibi %Dolumsuzlanmasıdır %d. Ayrıca, %weşittir [A-Za-z0-9_](yerel ayarınıza bağlı olarak diğer karakterler desteklenebilir).
Lars Gyrup Brink Nielsen

14

Bir dizedeki desenleristring.gmatch bulacağınız gibi , bu işlev de desenler arasındaki şeyleri bulur :

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

Varsayılan olarak boşlukla ayrılmış her şeyi döndürür.


6
+1. Diğer Lua yeni başlayanlar için not: bu bir yineleyici döndürür ve 'desenler arasında' dizenin başlangıcını ve sonunu içerir. (Bir acemi olarak bunları anlamaya çalışmalıydım.)
Darius Bacon

12

İşte işlevi:

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

Şöyle çağırın:

list=split(string_to_split,pattern_to_match)

Örneğin:

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


Daha fazla bilgi için buraya gidin:
http://lua-users.org/wiki/SplitJoin


7

Bu kısa çözümü beğendim

function split(s, delimiter)
    result = {};
    for match in (s..delimiter):gmatch("(.-)"..delimiter) do
        table.insert(result, match);
    end
    return result;
end

Bu benim favorim, çünkü çok kısa ve basit. Ne olduğunu tam olarak anlamıyorum, biri bana açıklayabilir mi?
altıgen

2
Nokta, sınırlayıcı olarak (veya potansiyel olarak başka herhangi bir model sihirli karakteri) kullanıldığında başarısız olur
TurboHz

6

Bir kediyi cildin birden fazla yolu olduğu için benim yaklaşımım:

Kod :

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

Çıktı : 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.

Açıklama :

gmatchBir yineleyici olarak işlev çalışır, maçın tüm dizeleri getirir regex. regexBir ayırıcı bulana kadar tüm karakterleri alır.


5

Bu yöntemi kullanabilirsiniz:

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) 

5

Bu cevapların birçoğu sadece tek karakterli ayırıcıları kabul eder veya kenar durumlarıyla (örneğin boş ayırıcılar) iyi ilgilenmez, bu yüzden daha kesin bir çözüm sağlayacağımı düşündüm.

Burada iki işlev vardır gsplitve splituyarlanan, kod içinde Scribunto MediaWiki uzantısı Wikipedia gibi wikilerde kullanılır. Kod GPL v2 altında lisanslanmıştır . Değişken adlarını değiştirdim ve kodu daha kolay anlaşılır hale getirmek için yorumlar ekledim ve ayrıca kodu Unicode dizeleri için Scribunto'nun desenleri yerine normal Lua dize desenlerini kullanacak şekilde değiştirdim. Orijinal kodun burada test senaryoları vardır .

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

Kullanılan splitfonksiyona bazı örnekler :

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

5

başkalarında görülmeyen bir yol

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

4

Basitçe bir sınırlayıcıda oturuyor

local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
    print(x)
end

3

Yukarıdaki örnekleri kendi fonksiyonumu oluşturmak için kullandım. Ama benim için eksik olan parça otomatik olarak sihirli karakterlerden kaçıyordu.

İşte katkım:

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

Bu benim de büyük sorunumdu. Bu sihirli karakterler ile harika çalışıyor, güzel biri
Andrew White

1

Penlight kütüphanesini kullanabilirsiniz . Bu, listeyi çıktılayan sınırlayıcıyı kullanarak dizeyi bölme işlevine sahiptir.

Lua'da programlama ve kayıp sırasında ihtiyaç duyabileceğimiz birçok işlevi yerine getirdi.

İşte kullanmak için örnek.

> 
> stringx = require "pl.stringx"
> 
> str = "welcome to the world of lua"
> 
> arr = stringx.split(str, " ")
> 
> arr
{welcome,to,the,world,of,lua}
> 

0

Kullanım durumuna bağlı olarak, bu yararlı olabilir. Tüm metni bayrakların her iki tarafında keser:

b = "This is a string used for testing"

--Removes unwanted text
c = (b:match("a([^/]+)used"))

print (c)

Çıktı:

string

0

Süper bu soruya geç, ancak herkes almak istediğiniz bölünme miktarını işleyen bir sürüm isterse .....

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

0

Lua'da program yaparsanız, burada şansınız kalmaz. Lua, kötü şöhretli bir şekilde kötü şöhretli olan bir programlama dilidir, çünkü yazarları asla standart kütüphanede "" bölünmüş işlevini uygulamadılar ve bunun yerine neden yapmadıkları ve yapmadıkları konusunda 16 ekran açıklaması ve topal bahane yazdılar, neredeyse hemen hemen herkes ama mola için işe garantili sayısız yarım çalışan örneklerle serpiştirildiği senin köşe durumda. Bu sadece Lua'nın son teknoloji ürünüdür ve Lua'da program yapan herkes dişlerini sıkmaya ve karakterleri tekrarlamaya başlar. Var olan, bazen daha iyi olan birçok çözüm vardır , ancak güvenilir bir şekilde daha iyi olan tamamen sıfır çözüm vardır .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.