Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 在表中插入字符串的带引号和不带引号的部分_String_Lua_Lua Patterns - Fatal编程技术网

String 在表中插入字符串的带引号和不带引号的部分

String 在表中插入字符串的带引号和不带引号的部分,string,lua,lua-patterns,String,Lua,Lua Patterns,我一直在研究saycommand系统的这一部分,它应该分离字符串的各个部分,并将它们放在一个表中,该表被发送到一个函数,该函数在字符串的开头被查询。例如,这看起来像是!保存1或!传送0 1或!告诉5“私人信息” 我希望将此字符串转换为表格: [[1 2 word 2 9 'more words' 1 "and more" "1 2 34"]] (字符串的每个非引用部分都有自己的键,引用部分被分组到一个键中) 我已经尝试过用Lua模式来实现这一点,但我一直在试图找出如何捕获带引号和不带引号的字

我一直在研究saycommand系统的这一部分,它应该分离字符串的各个部分,并将它们放在一个表中,该表被发送到一个函数,该函数在字符串的开头被查询。例如,这看起来像是
!保存1
!传送0 1或
!告诉5“私人信息”


我希望将此字符串转换为表格:

[[1 2 word 2 9 'more words' 1 "and more" "1 2 34"]]
(字符串的每个非引用部分都有自己的键,引用部分被分组到一个键中)

我已经尝试过用Lua模式来实现这一点,但我一直在试图找出如何捕获带引号和不带引号的字符串片段。我试过很多东西,但都没用

我当前的模式尝试如下所示:

a, d = '1 2 word 2 9 "more words" 1 "and more" "1 2 34"" ', {}

     --    previous attempts
    --[[
         This one captures quotes
     a:gsub('(["\'])(.-)%1', function(a, b) table.insert(d, b) end)

         This one captures some values and butchered quotes,
         which might have to do with spaces in the string
     a:gsub('(["%s])(.-)%1', function(a, b) table.insert(d, b) end)

         This one captures every value, but doesn't take care of quotes
     a:gsub('(%w+)', function(a) table.insert(d, a) end)

         This one tries making %s inside of quotes into underscores to
         ignore them there, but it doesn't work
     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)

         This one was a wild attempt at cracking it, but no success
     a:gsub('["\']([^"\']-)["\'%s]', function(a) table.insert(d, a) end)
    --]]

    --    This one adds spaces, which would later be trimmed off, to test
    --    whether it helped with the butchered strings, but it doesn't
a = a:gsub('(%w)(%s)(%w)', '%1%2%2%3')
a:gsub('(["\'%s])(.-)%1', function(a, b) table.insert(d, b) end)
for k, v in pairs(d) do
    print(k..' = '..v)
end

对于简单的命令来说,这不是必需的,而是像
这样更复杂的命令!告诉1 2 3 4 5“发送给五个人的私人消息”
确实需要它,首先检查它是否发送给多个人,然后确定消息是什么

接下来,我想添加像
这样的命令!给1 2 3“成分:材料\u铁:weapontype”“食物:卡路里”
,它应该为三个不同的人添加两个项目,将从这样一个系统中受益匪浅



如果这在Lua模式中是不可能的,我会尝试使用for循环之类的,但我真的觉得我遗漏了一些明显的东西。我是不是想得太多了?

您不能使用Lua模式处理带引号的字符串。您需要显式地解析字符串,如下面的代码所示

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

当您需要进行需要不同嵌套级别或令牌计数平衡(如括号
()
)的解析时,Lua字符串模式和regex通常不太适合这种情况。但Lua还有另一个功能强大的工具来处理该需求:

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)* '"'
  ]]
语法中当前没有捕获,因此
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)* } '"'
  ]]
您应该获得类似以下内容的输出:

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"
}
local cmdgrammar =
  [[
    saycmd  <- '!' {| {:cmd: cmd :} {:extra: extra :} |}
    cmd     <- %a%w+
    extra   <- {| (singlequote / doublequote / { unquote } / .)* |}
    unquote <- %w+
    singlequote   <- "'" { (unquote / %s)* } "'"
    doublequote   <- '"' { (unquote / %s)* } '"'
  ]]
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"
}