Câu trả lời:
Đây là giải pháp thực sự đơn giản của tôi. Sử dụng chức năng gmatch để chụp các chuỗi chứa ít nhất một ký tự của bất kỳ ký tự nào ngoài dấu phân cách mong muốn. Dấu phân cách là ** any * khoảng trắng (% s trong Lua) theo mặc định:
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
.
'foo,,bar'
. Bạn nhận được {'foo','bar'}
thay vì{'foo', '', 'bar'}
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
Nếu bạn đang tách một chuỗi trong Lua, bạn nên thử các phương thức string.gmatch () hoặc string.sub (). Sử dụng phương thức string.sub () nếu bạn biết chỉ mục bạn muốn tách chuỗi tại hoặc sử dụng chuỗi.gmatch () nếu bạn sẽ phân tích chuỗi để tìm vị trí để phân tách chuỗi tại.
Ví dụ sử dụng string.gmatch () từ Tài liệu tham khảo Lua 5.1 :
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Nếu bạn chỉ muốn lặp lại các mã thông báo, thì điều này khá gọn gàng:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Đầu ra:
một,
hai
và
3!
Giải thích ngắn: mẫu "[^% s] +" khớp với mọi chuỗi không trống ở giữa các ký tự khoảng trắng.
%S
tương đương với mẫu bạn đã đề cập, cũng như %S
phủ định %s
, giống như %D
phủ định %d
. Ngoài ra, %w
bằng [A-Za-z0-9_]
(các ký tự khác có thể được hỗ trợ tùy thuộc vào ngôn ngữ của bạn).
Cũng như string.gmatch
sẽ tìm thấy các mẫu trong một chuỗi, hàm này sẽ tìm thấy những thứ giữa các mẫu:
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
Theo mặc định, nó trả về bất cứ thứ gì được phân tách bằng khoảng trắng.
Đây là chức năng:
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
Gọi nó như:
list=split(string_to_split,pattern_to_match)
ví dụ:
list=split("1:2:3:4","\:")
Để biết thêm chi tiết tại đây:
http://lua-users.org/wiki/SplitJoin
Tôi thích giải pháp ngắn này
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
Bởi vì có nhiều hơn một cách để lột da một con mèo, đây là cách tiếp cận của tôi:
Mã số :
#!/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
Đầu ra :
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.
Giải thích :
Các gmatch
chức năng hoạt động như một iterator, rồi nó lấy tất cả các chuỗi trận đấu regex
. Việc regex
lấy tất cả các ký tự cho đến khi nó tìm thấy một dấu phân cách.
Bạn có thể sử dụng phương pháp này:
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)
Rất nhiều câu trả lời trong số này chỉ chấp nhận các dấu phân cách một ký tự hoặc không xử lý tốt các trường hợp cạnh (ví dụ: các dấu tách trống), vì vậy tôi nghĩ rằng tôi sẽ cung cấp một giải pháp dứt khoát hơn.
Đây là hai chức năng gsplit
và split
được điều chỉnh từ mã trong phần mở rộng Scribunto MediaWiki , được sử dụng trên các wiki như Wikipedia. Mã được cấp phép theo GPL v2 . Tôi đã thay đổi tên biến và thêm nhận xét để làm cho mã dễ hiểu hơn một chút và tôi cũng đã thay đổi mã để sử dụng các mẫu chuỗi Lua thông thường thay vì các mẫu của Scribunto cho chuỗi Unicode. Mã ban đầu có các trường hợp thử nghiệm ở đây .
-- 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
Một số ví dụ về split
chức năng được sử dụng:
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
Chỉ đơn giản là ngồi trên một dấu phân cách
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
Tôi đã sử dụng các ví dụ trên để chế tạo chức năng của riêng tôi. Nhưng mảnh còn thiếu đối với tôi đã tự động thoát khỏi các nhân vật ma thuật.
Đây là đóng góp của tôi:
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
Bạn có thể sử dụng thư viện penlight . Điều này có chức năng phân tách chuỗi bằng cách sử dụng dấu phân cách mà danh sách đầu ra.
Nó đã thực hiện nhiều chức năng mà chúng ta có thể cần trong khi lập trình và thiếu trong Lua.
Đây là mẫu để sử dụng nó.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
Rất muộn cho câu hỏi này, nhưng trong trường hợp bất cứ ai cũng muốn một phiên bản xử lý số lượng chia tách bạn muốn nhận .....
-- 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
Nếu bạn lập trình ở Lua, bạn sẽ hết may mắn ở đây. Lua là ngôn ngữ lập trình nổi tiếng khét tiếng bởi vì các tác giả của nó không bao giờ thực hiện "chức năng phân tách" trong thư viện tiêu chuẩn, và thay vào đó đã viết 16 màn hình giải thích và lý do khập khiễng về lý do tại sao họ không và sẽ không, xen kẽ với nhiều ví dụ nửa hoạt động gần như được đảm bảo để làm việc cho hầu hết mọi người nhưng phá vỡ trong trường hợp góc của bạn . Đây chỉ là trạng thái nghệ thuật của Lua và tất cả những người lập trình ở Lua chỉ đơn giản là nghiến răng và lặp đi lặp lại qua các nhân vật. Có rất nhiều giải pháp tồn tại đôi khi tốt hơn, nhưng chính xác là không có giải pháp nào tốt hơn đáng tin cậy .