【问题标题】:Lua: Quoted arguments passed as one in functionLua:带引号的参数在函数中作为一个传递
【发布时间】:2016-01-22 20:45:54
【问题描述】:

我正在尝试简化脚本,但我的尝试失败了。我正在制作一个函数,它将传递给定的参数并将它们转换为索引表,但我希望能够传递带引号和不带引号的类似函数,并让函数认识到带引号的参数被视为一个值,同时也尊重非- 引用的参数。

例如:

ma​​kelist 狗“棕鼠”猫虎“彩色鹦鹉”

应该返回如下索引表:

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"

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

【问题讨论】:

    标签: lua pattern-matching


    【解决方案1】:
    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
    

    【讨论】:

    • 什么,这次不评论了?! ;) 这在不平衡的报价上失败;例如,试试foo "unbalanced,尽管有人可能会说这是一种美德。
    • 哈哈,我想这是一种美德!这方面的答案真棒!哇,我很惊讶,你实际上回答而不是评论!谢谢,叶戈尔!
    【解决方案2】:

    简单地分割空格并连接引号内的元素可能更容易。这样的事情可能会奏效(我添加了几个测试用例):

    function makelist(str)
      local params, quoted = {}, false
      for sep, word in str:gmatch("(%s*)(%S+)") do
        local word, oquote = word:gsub('^"', "") -- check opening quote
        local word, cquote = word:gsub('"$', "") -- check closing quote
        -- flip open/close quotes when inside quoted string
        if quoted then -- if already quoted, then concatenate
          params[#params] = params[#params]..sep..word
        else -- otherwise, add a new element to the list
          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
    

    【讨论】:

    • 这在平衡引号上失败:"terminated by space " next
    • 在这方面做得很好! Egor 有点简单,但是伙计,我真的希望我能给每个人都接受的答案。相反,我希望每个人都支持所有这些好答案!谢谢!
    • 应该修复以空格开头/结尾的字符串。
    【解决方案3】:

    首先感谢您的提问,让我了解了 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
    

    【讨论】:

    • 很高兴能够帮助您学习一些东西!哈哈!有时,就我对 Lua 的了解而言,我倾向于让事情变得困难。我给你一个,因为你的答案完全震撼,但接受的答案在你做之前完成了同样的事情。但是主要的道具!
    猜你喜欢
    • 2013-02-13
    • 2012-12-16
    • 2015-10-29
    • 2021-03-30
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    • 2016-07-22
    相关资源
    最近更新 更多