2009-09-15 45 views
123

我需要做一個簡單的字符串拆分,但似乎沒有這個功能,我測試的手動方式似乎沒有工作。我會怎麼做?在Lua中分割字符串?

回答

76

請參閱Splitting Strings

這裏是拆分 字符串轉換成子, 打破 出現一些分隔 (字符,字符集,或 模式原始字符串列表的多種方式)。這通常稱爲 字符串split [2]函數。

+2

不幸的是,頁面已被然後進行編輯(雖然它是關於同一主題的),你所引用的通道不會在頁面上發生。這就是爲什麼它是理想的避免只有鏈接的答案,並且實際上在答案中包含了相關信息。 – ShreevatsaR 2018-01-25 23:56:45

27

如果你在分裂一個字符串在Lua中,你應該嘗試string.gmatch()或string.sub()方法。如果您知道要將字符串拆分的索引,請使用string.sub()方法,如果要解析字符串以查找拆分字符串的位置,請使用string.gmatch()。

實施例使用string.gmatch()從Lua 5.1 Reference Manual

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

我從那個lua用戶頁面「借用」了一個實現,無論如何感謝 – RCIX 2009-09-15 16:56:02

10

下面是函數:

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

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 

默認情況下,返回由空格分隔的任何內容。

+5

+1。請注意任何其他Lua初學者:這將返回一個迭代器,'模式之間'包含字符串的開始和結尾。 (作爲一個新手,我不得不嘗試把它們弄清楚。) – 2010-07-11 23:26:55

22

如果你只是想遍歷令牌,這是相當整潔:

line = "one, two and 3!" 

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

輸出:

之一,

3!

簡短解釋:「[^%s] +」模式匹配空格字符之間的每個非空字符串。

+0

模式'%S'等於您提到的模式,因爲'%S'是'%s'的否定,就像'%D'是'%d'的否定。 此外,'%w'等於'[A-Za-z0-9_]'(根據您的區域設置可能會支持其他字符)。 – 2014-01-02 22:00:46

4

您可以使用此方法:

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

這是我非常簡單的解決方案。使用gmatch函數來捕獲至少包含除希望的分隔符之外的任何其他任何字符的字符串。該分離器是任何空白(在Lua%S)默認:

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

謝謝。 **只是**我在找什麼。 – Nicholas 2012-06-03 19:33:12

+3

哇,這整個問題的第一個答案,實際上有一個函數返回一個表。但請注意,t和我需要「本地」修飾符,因爲它是覆蓋全局變量。 :) – cib 2013-04-18 18:05:38

+1

這工作。它只適用於單個字符分隔符。要按字符串拆分(例如XML標籤),請將匹配模式更改爲「(.-)(」.. sep ..「)」「。注意:如果字符串以sep結尾,則最後的匹配將失敗。在輸入字符串的末尾添加換行符或任何字符以解決此問題。 – 2014-07-30 09:17:31

6

我喜歡這個簡短的解決方案

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

這是我的最愛,因爲它太短了,簡單。 我不太明白會發生什麼事,有人可以向我解釋嗎? – hexagonest 2013-11-24 04:04:27

+1

使用點作爲分隔符(或潛在的任何其他模式魔術字符)時失敗 – TurboHz 2014-04-16 11:39:22

5

因爲有對皮膚一隻貓的方法不止一種,這裏是我的方法:

代碼

#!/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功能可以作爲一個迭代器,它獲取所有匹配regex的字符串。 regex接收所有字符,直到找到分隔符。

1

我用上面的例子來製作我自己的功能。但是對我來說缺失的部分是自動逃離魔法角色。

這裏是我的貢獻:

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

這也是我的大問題。這對神奇角色非常有用,很好 – 2016-06-03 06:08:24

0

只需坐在分隔符

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

很多這些答案只接受單字符分隔符,或者不符合邊緣的情況下處理好(例如空的分隔符),所以我想我會提供一個更確定的解決方案。

這裏有兩個功能,gsplitsplit,適於在Scribunto MediaWiki extension,這是在像Wikipedia維基使用來自code。該代碼根據GPL v2獲得許可。我已經更改了變量名稱並添加了註釋以使代碼更易於理解,並且我還更改了代碼以使用常規Lua字符串模式而不是Scribunto的Unicode字符串模式。原始代碼有測試案例here

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