Lua中如何分割字符串?
我需要对一个字符串进行简单的分割,但好像没有这样的函数,我测试的手动方式似乎也不起作用。我该怎么做?
原文链接 https://stackoverflow.com/questions/1426954
以下是函数:
function split(pString, pPattern)
local Table = {} -- 注意:在Lua-5.0中使用{n = 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","\:")
就像string.gmatch
会在字符串中查找_pattern_一样,这个函数将查找在模式之间的_things_:
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
默认情况下,它返回由空格分隔的任何内容。
如果您只想遍历标记,这样就很不错:
line = "one, two and 3!"
for token in string.gmatch(line, "[^%s]+") do
print(token)
end
输出:
one,
two
and
3!
简短的解释:"[^%s]+"模式匹配在空格字符之间的每个非空字符串。
你可以使用这个方法:
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) -- 使用 string:split 方法获取按照定界符 pattern 分割后的字符串列表
以下是我非常简单的解决方法。使用 gmatch()
函数来捕获包含至少一个除了所需分隔符的任意字符的字符串。默认情况下,分隔符是 任意 空白符(在 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
我喜欢这个简短的解决方案
function split(s, delimiter)
result = {};
for match in (s..delimiter):gmatch("(.-)"..delimiter) do
table.insert(result, match);
end
return result;
end
因为有多种方法来解决问题,这里是我的做法:
代码:
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(text, delim)
--根据文本和分隔符(仅一个字符)返回字段的数组
local result = {}
local magic = "().%+-*?[]^$"
if delim == nil then
delim = "%s"
elseif string.find(delim, magic, 1, true) then
--转义特殊字符
delim = "%"..delim
end
local pattern = "[^"..delim.."]+"
for w in string.gmatch(text, pattern) do
table.insert(result, w)
end
return result
end
仅仅坐在一个分隔符上
local str = 'one,two'
local regxEverythingExceptComma = '([^,]+)'
for x in string.gmatch(str, regxEverythingExceptComma) do
print(x)
end
很多答案只接受单字符分隔符,或者不能很好地处理边缘情况(例如空分隔符),所以我想提供一个更权威的解决方案。
下面是两个函数,gsplit
和 split
,改编自 Scribunto MediaWiki 扩展 中的 代码,该扩展用于维基百科等维基网站。该代码在 GPL v2 下获得许可。我已经更改了变量名称并添加了注释,使代码更易于理解,并且还更改了代码以使用常规的 Lua 字符串模式,而不是 Scribunto 的 Unicode 字符串模式。原始代码的测试用例在此处。
-- gsplit: 迭代由模式分隔的字符串中的子字符串
--
-- 参数:
-- text (string) - 要迭代的字符串
-- pattern (string) - 分隔符模式
-- plain (boolean) - 如果为 true(或真值),则将模式解释为普通字符串
-- 而不是 Lua 模式
--
-- 返回: 迭代器
--
-- 用法:
-- 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
-- 空分隔符!
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: 将字符串分割为由模式分隔的子字符串。
--
-- 参数:
-- text (string) - 要迭代的字符串
-- pattern (string) - 分隔符模式
-- plain (boolean) - 如果为 true(或真值),则将模式解释为普通字符串
-- 而不是 Lua 模式
--
-- 返回: table (一个包含子字符串的序列表)
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 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
你可以使用penlight库。其中有一个使用分隔符拆分字符串并输出列表的函数。
它实现了许多在Lua中编程时可能需要的函数,这些函数在Lua中缺失。
以下是使用示例:
>
> stringx = require "pl.stringx"
>
> str = "welcome to the world of lua"
>
> arr = stringx.split(str, " ")
>
> arr
{welcome,to,the,world,of,lua}
>
根据使用情况,这可能很有用。它剪切旗帜两侧的所有文本:
b = "This is a string used for testing"
--Removes unwanted text
c = (b:match("a([^/]+)used"))
print (c)
输出:
string
-- 使用分隔符和限制将字符串拆分成表格
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 4.0中有效的例程,返回一个由sep限定的inputstr中的子字符串组成的表格t:
function string_split(inputstr, sep)
local inputstr = inputstr .. sep
local idx, inc, t = 0, 1, {}
local idx_prev, substr
repeat
idx_prev = idx
inputstr = strsub(inputstr, idx + 1, -1) -- 去掉包含最后一次strfind寻找到的匹配(或最初为空),保留其余部分(或最初的全部)
idx = strfind(inputstr, sep) -- 找到分隔符首次出现的0-based r_index
if idx == nil then break end -- 如果没找到就结束
substr = strsub(inputstr, 0, idx) -- 提取分隔符之前出现的子字符串(即下一个定界符之前的数据区域)
substr = gsub(substr, "[%c" .. sep .. " ]", "") -- 消除控制字符、分隔符和空格
t[inc] = substr -- 存储子字符串(即数据区域)
inc = inc + 1 -- 迭代到下一个
until idx == nil
return t
end
这个简单的测试
inputstr = "the brown lazy fox jumped over the fat grey hen ... or something."
sep = " "
t = {}
t = string_split(inputstr,sep)
for i=1,15 do
print(i, t[i])
end
输出:
--> t[1]=the
--> t[2]=brown
--> t[3]=lazy
--> t[4]=fox
--> t[5]=jumped
--> t[6]=over
--> t[7]=the
--> t[8]=fat
--> t[9]=grey
--> t[10]=hen
--> t[11]=...
--> t[12]=or
--> t[13]=something.
我发现许多其他回答存在无法处理的边缘情况 (例如,当给定的字符串包含 #
,{
或 }
字符,或者当给定分隔符字符如 %
需要转义时)。因此,这里是我选择的实现方式:
local function newsplit(delimiter, str)
assert(type(delimiter) == "string")
assert(#delimiter > 0, "Must provide non empty delimiter")
-- 如果需要,添加转义字符
delimiter = delimiter:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%0")
local start_index = 1
local result = {}
while true do
local delimiter_index, _ = str:find(delimiter, start_index)
if delimiter_index == nil then
table.insert(result, str:sub(start_index))
break
end
table.insert(result, str:sub(start_index, delimiter_index - 1))
start_index = delimiter_index + 1
end
return result
end
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
如果你想要在 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