लुआ में विभाजित स्ट्रिंग?


160

मुझे एक स्ट्रिंग का सरल विभाजन करने की आवश्यकता है, लेकिन इसके लिए कोई फ़ंक्शन नहीं लगता है, और मैंने जिस तरह से परीक्षण किया वह काम नहीं करता था। मैं यह कैसे करूंगा?


जवाबों:


96

यहाँ मेरा वास्तव में सरल समाधान है। स्ट्रिंग्स को कैप्चर करने के लिए gmatch फ़ंक्शन का उपयोग करें जिसमें वांछित विभाजक के अलावा किसी अन्य चीज़ का कम से कम एक वर्ण होता है । विभाजक डिफ़ॉल्ट रूप से कोई भी * व्हाट्सएप (Lua में% 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
धन्यवाद। बस मैं जो चाह रहा था।
निकोलस

3
वाह, इस पूरे सवाल में पहला जवाब जो वास्तव में एक फ़ंक्शन है जो एक तालिका लौटाता है। हालांकि, ध्यान दें कि मुझे "स्थानीय" संशोधक की आवश्यकता है, क्योंकि आप ग्लोबल्स को ओवरराइट कर रहे हैं। :)
cib

3
जैसा कि अन्य ने बताया है, आप इसे [i] = str के बजाय table.insert (t, str) का उपयोग करके सरल कर सकते हैं और फिर आपको i = 1 या i = i +1
James Newton

2
यदि स्ट्रिंग में रिक्त मान शामिल नहीं हैं, जैसे 'foo,,bar'। आप {'foo','bar'}इसके बजाय{'foo', '', 'bar'}
andras

5
ये सही है। अगला संस्करण उस मामले में काम करेगा: 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

यदि आप Lua में एक स्ट्रिंग को विभाजित कर रहे हैं, तो आपको string.gmatch () या string.sub () विधियों का प्रयास करना चाहिए। अगर आप स्ट्रिंग को विभाजित करने की इच्छा रखते हैं, या आप स्ट्रिंग को विभाजित करने के लिए स्थान खोजने के लिए स्ट्रिंग को पार्स करेंगे () तो स्ट्रिंग का उपयोग करें।

Lua 5.1 संदर्भ मैनुअल से string.gmatch () का उपयोग करके उदाहरण :

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

मैं वैसे भी उस लुआ-उपयोगकर्ता पृष्ठ से एक कार्यान्वयन "धन्यवाद"
RCIX

24

यदि आप टोकन के ऊपर से चलना चाहते हैं, तो यह बहुत साफ है:

line = "one, two and 3!"

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

आउटपुट:

एक,

दो

तथा

3!

संक्षिप्त विवरण: "[^% s] +" पैटर्न अंतरिक्ष वर्णों के बीच हर गैर-रिक्त स्ट्रिंग से मेल खाता है।


2
पैटर्न %Sआपके द्वारा उल्लेखित के बराबर है, जैसा %Sकि नकारात्मकता है %s, जैसा %Dकि नकारात्मकता है %d। इसके अतिरिक्त, (आपके स्थान के आधार पर अन्य वर्ण समर्थित हो सकते हैं) के %wबराबर है [A-Za-z0-9_]
लार्स सिरप ब्रिंक नीलसन

14

जैसे स्ट्रिंग में पैटर्नstring.gmatch मिलेंगे , यह फ़ंक्शन पैटर्न के बीच चीजों को खोजेगा:

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

डिफ़ॉल्ट रूप से यह व्हाट्सएप द्वारा जो कुछ भी अलग किया जाता है, उसे वापस करता है।


6
+1। किसी अन्य Lua शुरुआती पर ध्यान दें: यह एक पुनरावृत्ति देता है, और 'पैटर्न के बीच' में स्ट्रिंग की शुरुआत और अंत शामिल है। (एक नौसिखिया के रूप में मुझे इन बातों को जानने की कोशिश करनी थी।)
डेरिक बेकन

12

यहाँ समारोह है:

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

इसे कॉल करें जैसे:

list=split(string_to_split,pattern_to_match)

उदाहरण के लिए:

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


यहाँ और जाने के लिए:
http://lua-users.org/wiki/SplitJoin


7

मुझे यह छोटा उपाय पसंद है

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

यह मेरा पसंदीदा है, क्योंकि यह बहुत छोटा और सरल है। मुझे समझ में नहीं आता कि क्या होता है, क्या कोई मुझे समझा सकता है?
हेक्सागोनस्ट

2
यह तब विफल हो जाता है जब डॉट को सीमांकक के रूप में उपयोग किया जाता है (या संभावित रूप से किसी अन्य पैटर्न का जादुई चरित्र)
TurboHz

6

क्योंकि एक बिल्ली की त्वचा के लिए एक से अधिक तरीके हैं, यहां मेरा दृष्टिकोण है:

कोड :

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

आउटपुट : 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.

स्पष्टीकरण :

gmatchपुनरावर्तक के रूप में समारोह काम करता है, यह है कि मैच सभी स्ट्रिंग्स को हासिल करेगा regexregexजब तक यह एक विभाजक पाता है सभी पात्रों लेता है।


5

आप इस विधि का उपयोग कर सकते हैं:

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

इनमें से बहुत सारे उत्तर केवल एकल-वर्ण विभाजकों को स्वीकार करते हैं, या किनारे के मामलों से अच्छी तरह से नहीं निपटते हैं (जैसे कि खाली विभाजक), इसलिए मैंने सोचा कि मैं एक अधिक निश्चित समाधान प्रदान करूंगा।

यहां दो कार्य हैं, gsplitऔर split, स्क्रिबुन्टो मीडियाविकि एक्सटेंशन में कोड से अनुकूलित है , जिसका उपयोग विकिपीडिया जैसे विकिपीडिया पर किया जाता है। कोड को GPL v2 के तहत लाइसेंस प्राप्त है । मैंने कोड को समझने में थोड़ा आसान बनाने के लिए चर नामों और जोड़ा टिप्पणियों को बदल दिया है, और मैंने यूनिकोड स्ट्रिंग्स के लिए स्क्रिबुन्टो के पैटर्न के बजाय नियमित लूआ स्ट्रिंग पैटर्न का उपयोग करने के लिए कोड भी बदल दिया है। मूल कोड में यहां परीक्षण मामले हैं

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

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

5

एक रास्ता दूसरों में नहीं देखा

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


3

मैंने अपने स्वयं के फ़ंक्शन को तैयार करने के लिए उपरोक्त उदाहरणों का उपयोग किया। लेकिन मेरे लिए लापता टुकड़ा स्वचालित रूप से जादू पात्रों से बच रहा था।

यहाँ मेरा योगदान है:

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

यह मेरा बड़ा मुद्दा भी था। यह जादू के पात्रों के साथ बहुत अच्छा काम करता है, एक अच्छा
एंड्रयू व्हाइट

1

आप पेनलाइट लाइब्रेरी का उपयोग कर सकते हैं । इसमें सीमांकक का उपयोग करके स्ट्रिंग को विभाजित करने के लिए एक फ़ंक्शन है जो सूची को आउटपुट करता है।

इसने कई ऐसे फंक्शन को लागू किया है जिनकी हमें प्रोग्रामिंग करते समय और लुआ में लापता होने की आवश्यकता हो सकती है।

यहाँ इसका उपयोग करने के लिए नमूना है।

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

0

उपयोग के मामले के आधार पर, यह उपयोगी हो सकता है। यह झंडे के दोनों ओर के सभी पाठों को काट देता है:

b = "This is a string used for testing"

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

print (c)

आउटपुट:

string

0

इस सवाल के लिए सुपर देर से, लेकिन मामले में कोई भी एक संस्करण चाहता है जो विभाजन की मात्रा को संभालता है जिसे आप प्राप्त करना चाहते हैं .....

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

यदि आप लुआ में कार्यक्रम करते हैं, तो आप यहां भाग्य से बाहर हैं। लुआ एक प्रोग्रामिंग भाषा है जो सिर्फ कुख्यात होने के लिए बदनाम है क्योंकि इसके लेखकों ने मानक पुस्तकालय में "" विभाजन फ़ंक्शन को कभी लागू नहीं किया, और इसके बजाय 16 स्क्रीनफुल स्पष्टीकरण और लंगड़ा बहाना लिखा कि क्यों और क्या नहीं किया; लगभग आधे-अधूरे काम के उदाहरणों से घिरा हुआ है जो लगभग सभी के लिए काम करने की गारंटी देते हैं लेकिन आपके कोने के मामले में टूट जाते हैं । यह सिर्फ कला की लुआ स्थिति है, और हर कोई जो लुआ में कार्यक्रम करता है, बस अपने दांतों को बंद कर देता है और पात्रों पर ध्यान केंद्रित करता है। अस्तित्व में बहुत सारे समाधान हैं जो कभी-कभी बेहतर होते हैं, लेकिन बिल्कुल शून्य समाधान जो मज़बूती से बेहतर होते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.