2016-10-20 25 views
4

区切り文字付きの区切り文字(lua)にsplit()関数を作成します。デフォルトはスペースです。 デフォルトは正常に動作しています。この問題は、関数にデリミタを付けると始まります。何らかの理由で、最後のサブストリングを戻しません。 機能:指定した区切り文字を持つ区切り文字を

function split(str,sep) 
if sep == nil then 
    words = {} 
    for word in str:gmatch("%w+") do table.insert(words, word) end 
    return words 
end 
return {str:match((str:gsub("[^"..sep.."]*"..sep, "([^"..sep.."]*)"..sep)))} -- BUG!! doesnt return last value 
end 

私はこれを実行しよう:

local str = "a,b,c,d,e,f,g" 
local sep = "," 
t = split(str,sep) 
for i,j in ipairs(t) do 
    print(i,j) 
end 

をし、私が手:

1 a 
2 b 
3 c 
4 d 
5 e 
6 f 

バグがどこにあるかを見つけ出すことはできません...

+1

としてそれをエスケープしていない場合%のようなセパレータは、問題を引き起こす可能性があります。しかしパターンは '[^、] *、'です。 PS。宣伝用https://github.com/moteus/lua-split。 – moteus

+0

これも参照してください:http://stackoverflow.com/questions/36957798/split-a-string-by-a-character-in-lua/36958689#36958689 – tonypdmtr

答えて

4

文字列を分割するとき、コーナーケースを避ける最も簡単な方法は、文字列に区切り文字を追加することです。リングが区切り文字で終了することはできません。

str = "a,b,c,d,e,f,g" 
str = str .. ',' 
for w in str:gmatch("(.-),") do print(w) end 

また、オプションの区切り文字でパターンを使用することができます。

str = "a,b,c,d,e,f,g" 
for w in str:gmatch("([^,]+),?") do print(w) end 

我々は非キャプチャしているので、実際には、我々は、オプションの区切り文字は必要ありません。区切り文字:

str = "a,b,c,d,e,f,g" 
for w in str:gmatch("([^,]+)") do print(w) end 
+0

シンプルでエレガントな...ありがとう! – DrorNohi

+1

私は、文字列に区切り文字で終わることができないときだけでなく、すべての場合に文字列に区切り文字を追加すると思います。文字列がデリミタで終わっている場合は、最後に空のマッチが得られます。 – tonypdmtr

+0

@tonypdmtr、これについてはっきりしている限り、それは問題ありません。 – lhf

0

は、ここで私は通常、すべての私の「分裂」のために使用し、スプリット機能が必要です:

function split(s, sep) 
    local fields = {} 

    local sep = sep or " " 
    local pattern = string.format("([^%s]+)", sep) 
    string.gsub(s, pattern, function(c) fields[#fields + 1] = c end) 

    return fields 
end 

t = split("a,b,c,d,e,f,g",",") 
for i,j in pairs(t) do 
    print(i,j) 
end 
0

"[^"..sep.."]*"..sepこれが問題の原因です。セパレータではなく、セパレータで区切られた文字列と一致しています。ただし、一致させる最後の部分文字列(g)の後ろにセパレータ文字はありません。

\0セパレータ("[^"..sep.."\0]*"..sep)は、文字列の先頭および/または末尾を表すため、この問題を解決する最も簡単な方法です。このようにして、区切り文字が続くのではなく、文字列の最後に続く、gはまだ一致と見なされます。

私はあなたのアプローチが一般的に過度に複雑であると言いたいと思います。第一に、セパレータを含まない個々の部分文字列にマッチすることができます。第二に、あなたがgmatch機能

local result = {} 
for field in your_string:gsub(("[^%s]+"):format(your_separator)) do 
    table.insert(result, field) 
end 
return result 

EDITを使用して-loop forでこれを行うことができます:上記のコードはもう少しシンプルに:

local pattern = "[^%" .. your_separator .. "]+" 
for field in string.gsub(your_string, pattern) do 
-- ...and so on (The rest should be easy enough to understand) 

EDIT2:あなたもあなたをエスケープする必要があることに注意してくださいセパレータ。あなたは、文字列の末尾にSEPしていないので、これがある%%

function escape(str) 
    return str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") 
end 
関連する問題