【发布时间】:2010-11-28 10:57:53
【问题描述】:
我需要对字符串进行简单的拆分,但似乎没有此功能,而且我测试的手动方式似乎不起作用。我该怎么做?
【问题讨论】:
我需要对字符串进行简单的拆分,但似乎没有此功能,而且我测试的手动方式似乎不起作用。我该怎么做?
【问题讨论】:
这是我非常简单的解决方案。使用 gmatch 函数捕获除所需分隔符之外至少包含 一个 字符的 anything 字符的字符串。默认情况下,分隔符是 **any* 空格(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
.
【讨论】:
'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()。
使用来自Lua 5.1 Reference Manual 的 string.gmatch() 的示例:
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 会在字符串中找到patterns,这个函数会找到between 模式的东西:
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
默认情况下,它返回由空格分隔的任何内容。
【讨论】:
如果你在 Lua 中编程,那么你在这里就不走运了。 Lua 是一种恰好臭名昭著的编程语言,因为它的作者从未在标准库中实现“拆分”函数,而是写了 16 个屏幕全屏的解释和蹩脚的借口来解释为什么他们没有和不会,穿插着许多半工作的例子,这些例子几乎可以保证对几乎所有人都有效,但会打破你的极端情况。这只是 Lua 最先进的技术,使用 Lua 编程的每个人最终都会咬紧牙关,迭代字符。存在许多有时更好的解决方案,但可靠更好的完全零解决方案。
【讨论】:
split() 或 PHP 的 explode() 或其他任何东西。但是由于 Lua 作者拒绝为 Lua 标准化一个解决方案,每个人都必须这样做。这是数十年来积累的成千上万的程序员小时。而且只有 LUA 作者可以标准化解决方案!
split() 或PHP 的explode() 可靠更好,要么推荐一些不可靠的东西。 “这是数十年来积累的成千上万的程序员小时”对于任何没有“包括厨房水槽”库的语言都是如此,包括 ANSI C,地球上最流行的语言,以及 Lua 故意最小化库的基础.这基本上是一个论点,即任何语言都不应该包含一个庞大的库。
函数如下:
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
【讨论】:
因为给猫剥皮的方法不止一种,所以这是我的方法:
代码:
#!/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 split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
【讨论】:
很多这些答案只接受单字符分隔符,或者不能很好地处理边缘情况(例如空分隔符),所以我想我会提供一个更明确的解决方案。
这里有两个函数,gsplit 和 split,改编自 Scribunto MediaWiki extension 中的 code,用于 Wikipedia 等 wiki。该代码在GPL v2 下获得许可。我更改了变量名称并添加了 cmets 以使代码更易于理解,并且我还更改了代码以使用常规 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
【讨论】:
你可以使用这个方法:
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)
【讨论】:
其他人看不到的方式
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
【讨论】:
只需坐在分隔符上
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
【讨论】:
您可以使用penlight library。这具有使用分隔符拆分字符串的功能,该分隔符输出列表。
它实现了许多我们在 Lua 中编程时可能需要和缺少的功能。
这是使用它的示例。
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
【讨论】:
我使用上面的例子来制作我自己的函数。但对我来说缺少的部分是自动逃脱魔法字符。
这是我的贡献:
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
【讨论】:
这个问题太晚了,但如果有人想要一个版本来处理你想要得到的拆分数量.....
-- 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
【讨论】:
根据用例,这可能很有用。它会剪切标志两侧的所有文本:
b = "This is a string used for testing"
--Removes unwanted text
c = (b:match("a([^/]+)used"))
print (c)
输出:
string
【讨论】: