Ответы:
Вот мое действительно простое решение. Используйте функцию gmatch для захвата строк, которые содержат хотя бы один символ чего-либо, кроме требуемого разделителя. Разделителем является ** любой * пробел (% s в Lua) по умолчанию:
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'
, Вы получаете {'foo','bar'}
вместо{'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
Если вы разбиваете строку в Lua, вам следует попробовать методы string.gmatch () или string.sub (). Используйте метод string.sub (), если вам известен индекс, по которому вы хотите разделить строку, или используйте string.gmatch (), если вы проанализируете строку, чтобы найти место для разделения строки.
Пример использования string.gmatch () из справочного руководства Lua 5.1 :
t = {}
s = "from=world, to=Lua"
for k, v in string.gmatch(s, "(%w+)=(%w+)") do
t[k] = v
end
Если вы просто хотите перебрать токены, это довольно аккуратно:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
Вывод:
один,
два
и
3!
Краткое объяснение: шаблон «[^% s] +» соответствует каждой непустой строке между пробелами.
%S
равен тому, который вы упомянули, как %S
и отрицание %s
, как %D
и отрицание %d
. Кроме того, %w
равно [A-Za-z0-9_]
(другие символы могут поддерживаться в зависимости от вашей локали).
Так же, как 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
По умолчанию он возвращает все, что разделено пробелами.
Вот функция:
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
Мне нравится это короткое решение
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
Поскольку существует более одного способа снятия шкуры с кошки, вот мой подход:
Код :
#!/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
принимает все символы, пока не найдет разделитель.
Вы можете использовать этот метод:
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)
Многие из этих ответов принимают только односимвольные разделители или плохо разбираются в крайних случаях (например, пустые разделители), поэтому я подумал, что смогу найти более определенное решение.
Вот две функции, gsplit
и split
, адаптированная из кода в расширении Scribunto MediaWiki , который используется на вики как Википедия. Код распространяется по лицензии GPL v2 . Я изменил имена переменных и добавил комментарии, чтобы немного облегчить понимание кода, а также изменил код, чтобы использовать обычные строковые шаблоны Lua вместо шаблонов Scribunto для строк Unicode. Оригинальный код имеет тестовые случаи здесь .
-- 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
Просто сидим на разделителе
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
Я использовал приведенные выше примеры для создания своей собственной функции. Но пропавшая часть для меня автоматически убегала от магических персонажей.
Вот мой вклад:
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
Вы можете использовать библиотеку Penlight . У этого есть функция для разделения строки, используя разделитель, который выводит список.
В нем реализованы многие функции, которые могут нам понадобиться при программировании и отсутствовать в Lua.
Вот пример для его использования.
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
Супер поздно на этот вопрос, но в случае, если кто-то хочет версию, которая обрабатывает количество расколов, которые вы хотите получить .....
-- 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
Если вы программируете на Lua, вам здесь не повезло. Lua - это единственный язык программирования, который просто печально известен своей печально известной репутацией, потому что его авторы никогда не реализовывали функцию «разделения» в стандартной библиотеке, а вместо этого написали 16 скриншотов с объяснениями и неубедительными оправданиями того, почему они этого не сделали и не будут вкраплен многочисленными полуработающими примерами, которые практически гарантированно сработают почти для всех, но не сработают в вашем угловом деле. Это просто уровень Lua, и каждый, кто программирует на Lua, просто сжимает зубы и перебирает персонажей. Существует множество решений, которые иногда лучше, но ровно нулевых решений, которые надежно лучше.