Lua:在函数中以引号括起来的参数作为整体传递

我正在尝试简化一个脚本,但我的尝试失败了。我正在编写一个函数,将给定的参数传递并将它们转换为索引表,但我希望能够传递带引号和不带引号的参数,并且函数能够识别到带引号的参数被认为是一个值,同时也尊重不带引号的参数。

例如:

makelist dog "brown mouse" cat tiger "colorful parrot"

应该返回一个索引表,如下所示:

list_table = {"dog", "brown mouse", "cat", "tiger", "colorful parrot"}

我编写的代码适用于带引号的参数,但它在不带引号的参数上出现问题,并且在此基础上,又将带引号的参数添加了一次。以下是我拥有的代码:

function makelist(str)
  require 'tprint'
  local list_table = {}
  for word in string.gmatch(str, '%b""') do
    table.insert(list_table, word)
  end
  for word in string.gmatch(str, '[^%p](%a+)[^%p]') do
    table.insert(list_table, word)
  end
  tprint(list_table)
end

我不明白为什么省略引号被忽略,并且还将第一个字母截掉。也就是说,这是我从tprint(一个打印表的函数,与代码不相关)接收到的输出:

makelist('dog "brown mouse" cat tiger "colorful parrot"')
1=""brown mouse""
2=""colorful parrot""
3="og"
4="rown"
5="mouse"
6="cat"
7="tiger"
8="olorful"
9="parrot"

正如您所看到的,'d','b'和'c'已经缺失。我需要做出以下修复措施,以便我可以获得以下输出:

1="brown mouse"
2="colorful parrot"
3="dog"
4="cat"
5="tiger"

或者最好的办法是,让它们保留作为参数指定的相同顺序,如果可能的话。

点赞
用户1847592
用户1847592
local function makelist(str)
  local t = {}
  for quoted, non_quoted in ('""'..str):gmatch'(%b"")([^"]*)' do
    table.insert(t, quoted ~= '""' and quoted:sub(2,-2) or nil)
    for word in non_quoted:gmatch'%S+' do
      table.insert(t, word)
    end
  end
  return t
end
2016-01-22 21:15:14
用户1442917
用户1442917

可能更容易的方法是在空格上进行拆分,并连接那些在引号内的元素。类似这样的代码可能会起作用(我添加了几个测试用例):

function makelist(str)
  local params, quoted = {}, false
  for sep, word in str:gmatch("(%s*)(%S+)") do
    local word, oquote = word:gsub('^"', "") -- 检查开头引号
    local word, cquote = word:gsub('"$', "") -- 检查结尾引号
    -- 当在引号内部时,交替开启/关闭引号
    if quoted then -- 如果已经引用,则连接
      params[#params] = params[#params]..sep..word
    else -- 否则,添加新元素到列表中
      params[#params+1] = word
    end
    if quoted and word == "" then oquote, cquote = 0, oquote end
    quoted = (quoted or (oquote > 0)) and not (cquote > 0)
  end
  return params
end
local list = makelist([[
dog "brown mouse" cat tiger " colorful parrot " "quoted"
in"quoted "terminated by space " " space started" next "unbalanced
]])
for k, v in ipairs(list) do print(k, v) end

这对我来说打印以下列表:

1   dog
2   brown mouse
3   cat
4   tiger
5    colorful parrot
6   quoted
7   in"quoted
8   terminated by space
9    space started
10  next
11  unbalanced
2016-01-22 21:15:26
用户1593987
用户1593987

首先感谢你的问题,让我学习了 Lua 的基础知识!

其次,我认为你在问题解决方案中有点走偏了。看到这个问题,我想为什么不先按双引号(")拆分一次,然后再选择按空格拆分呢?

这就是我想出来的:

function makelist(str)
  local list_table = {}
  i=0
  in_quotes = 1
  if str:sub(0,1) == '"' then
     in_quotes = 0
  end
  for section in string.gmatch(str, '[^"]+') do
    i = i + 1
    if (i % 2) == in_quotes  then
      for word in string.gmatch(section, '[^ ]+') do
         table.insert(list_table, word)
      end
    else
        table.insert(list_table, section)
    end
  end
  for key,value in pairs(list_table) do print(key,value) end
end

结果:

1   dog
2   brown mouse
3   cat
4   tiger
5   colorful parrot
2016-01-22 21:36:25