在表格中插入带引号和不带引号的字符串部分。
我一直在做一个说话命令系统的一部分,它应该将字符串的部分分离并将它们放入一个表中,然后将该表发送到一个函数中,在字符串的开头查询它。例如,!save 1,!teleport 0 1或!tell 5“私人消息”。
我想将此字符串转换为表格:
[[1 2 word 2 9 'more words' 1 "and more" "1 2 34"]]
(每个非引用部分的字符串都有自己的键,引用部分被分组为一个键)
1 = 1
2 = 2
3 = word
4 = 2
5 = 9
6 = more words
7 = 1
8 = and more
9 = 1 2 34
我尝试使用Lua模式来实现这个功能,但我卡在如何捕获字符串的引用和非引用部分上。我尝试了很多方法,但没有任何帮助。
我的当前模式尝试如下:
a,d ='1 2 word 2 9"more words"1"and"1 2 34“',{}
-- 先前的尝试
--[[
这个捕获引号
a:gsub('(["\'])(.-)%1',function(a,b)table.insert(d,b)end)
这个捕获一些值和损坏的引用,由于字符串中可能有空格,因此可能要做一些处理
a:gsub('(["%s])(.-)%1',function(a,b)table.insert(d,b)end)
这个捕获每个值,但不处理引用
a:gsub('(%w +)',function(a)table.insert(d,a)end)
这个尝试使引号内的%s变成下划线以忽略它们,但它不起作用
a = a:gsub('(%w“\')+)','%1%')
a:gsub('(["\'_])(.-)%1',function(a,b)table.insert(d,b)end)
a:gsub('(%w _ +)',function(a)table.insert(d,a)end)
这是一次突破的疯狂尝试,但没有成功
a:gsub('["\']([^"\']-)["\'%s]', function(a) table.insert(d, a) end)
--]]
-- 这个添加了空格,以后会被修剪掉,以测试是否有助于损坏的字符串,但它不起作用
a = a:gsub('(%w)(%s)(%w)','%1%2%2%3')
a:gsub('(["\'%s])(.-)%1',function(a,b)table.insert(d,b)end)
对于k,v in pairs(d)做
print(k..' ='..v)
结束
这对于简单的命令是不需要的,但是像!tell 1 2 3 4 5“发送给五个人的私人消息”这样更复杂的命令确实需要它,首先要检查它是否发送给多个人,然后找出消息是什么。
在更远的路上,我想添加像“!give 1 2 3“component:material_iron:weapontype”“food:calories””这样的命令,它应该向三个不同的人添加两个物品,这将从这样的系统中获益。
如果Lua模式无法实现此目的,我将尝试使用循环等来实现它,但我确实感到自己缺少了一些明显的东西。我是在过度思考吗?
Lua 字符串模式和正则表达式在需要进行嵌套层数或令牌数量平衡,例如括号 ( ) 的解析时不太适用。但是,Lua 中另一个强大的工具可以处理这种情况:LPeg。
LPeg 语法有点过时,需要一些适应时间,因此我将使用 lpeg re 模块来使其更易于理解。请记住,任何你在一种语法形式中可以做的事情也可以在另一种形式中表达出来。
首先,定义解析你的格式描述的语法:
local re = require 're'
local cmdgrammar =
[[
saycmd <- '!' cmd extra
cmd <- %a%w+
extra <- (singlequote / doublequote / unquote / .)*
unquote <- %w+
singlequote <- "'" (unquote / %s)* "'"
doublequote <- '"' (unquote / %s)* '"'
]]
接下来,编译语法并用它来匹配一些测试示例:
local cmd_parser = re.compile(cmdgrammar)
local saytest =
{
[[!save 1 2 word 2 9 'more words' 1 "and more" "1 2 34"]],
[[!tell 5 "a private message"]],
[[!teleport 0 1]],
[[!say 'another private message' 42 "foo bar" baz]],
}
目前该语法没有捕获规则,因此 re.match 返回它能够匹配的字符串中的最后一个字符位置 +1。这意味着成功解析将返回字符串的完整字符数 +1,并因此是你的语法的有效实例。
for _, test in ipairs(saytest) do
assert(cmd_parser:match(test) == #test + 1)
end
现在,有趣的部分来了。一旦你的语法按照你的要求工作,你现在可以添加捕获,这些捕获可以自动将结果提取到一个 Lua 表中,而且工作量相对较小。这是最终语法规范和表捕获:
local cmdgrammar =
[[
saycmd <- '!' {| {:cmd: cmd :} {:extra: extra :} |}
cmd <- %a%w+
extra <- {| (singlequote / doublequote / { unquote } / .)* |}
unquote <- %w+
singlequote <- "'" { (unquote / %s)* } "'"
doublequote <- '"' { (unquote / %s)* } '"'
]]
再次运行测试并转储 re.match 结果:
for i, test in ipairs(saytest) do
print(i .. ':')
dump(cmd_parser:match(test))
end
你应该得到类似于以下的输出:
lua say.lua
1:
{
extra = {
"1",
"2",
"word",
"2",
"9",
"more words",
"1",
"and more",
"1 2 34"
},
cmd = "save"
}
2:
{
extra = {
"5",
"a private message"
},
cmd = "tell"
}
3:
{
extra = {
"0",
"1"
},
cmd = "teleport"
}
4:
{
extra = {
"another private message",
"42",
"foo bar",
"baz"
},
cmd = "say"
}
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在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 模式处理带引号的字符串。你需要显式地解析字符串,如下面的代码所示。
--定义 split 函数 function split(s) local t={} local n=0 local b,e=0,0 while true do b,e=s:find("%s*",e+1) b=e+1 if b>#s then break end n=n+1 if s:sub(b,b)=="'" then b,e=s:find(".-'",b+1) t[n]=s:sub(b,e-1) elseif s:sub(b,b)=='"' then b,e=s:find('.-"',b+1) t[n]=s:sub(b,e-1) else b,e=s:find("%S+",b) t[n]=s:sub(b,e) end end return t --返回切割完成的字符串数组 end --定义输入字符串 s=[[1 2 word 2 9 'more words' 1 "and more" "1 2 34"]] print(s) --输出输入字符串 t=split(s) --对输入字符串进行切割 for k,v in ipairs(t) do print(k,v) --输出切割结果 end