【问题标题】:Lua string patternLua 字符串模式
【发布时间】:2016-02-06 21:20:05
【问题描述】:

这是我的代码:

local code = [[
    local a = 1

    local b = 2
]]

local y = 0

for Paragraph in string.gmatch(code,"[^\n]+") do
    print(Paragraph)
    for Word in string.gmatch(Paragraph, "[^ ]+") do        

    end
    y = y + 1
end

问题是模式无法识别我的空段落我该如何解决这个问题?

如果你运行代码,你就会明白我的意思

输出是:

local a = 1
local b = 2

应该是:

--space
local a = 1
--space
local b = 2
--space

【问题讨论】:

    标签: lua


    【解决方案1】:

    应该是:

        --space
        local a = 1
    

    你不会得到第一个空格,因为 Lua 长字符串会丢弃第一个换行符。


    您的问题是您在"[^\n]+" 上的匹配匹配至少一个 字符,该字符不是换行符。空行不匹配(换行符之间没有字符),因此不会显示。

    现在您可以将其更改为 "[^\n]*",如下所示:

    for Paragraph in string.gmatch(code,"[^\n]*") do
        print("Line=", Paragraph)
        for Word in string.gmatch(Paragraph, "[^ ]+") do        
          print ("Word=", Word)
        end
    end
    

    但这有一个不同的问题:

    Line=     local a = 1
    Word= local
    Word= a
    Word= =
    Word= 1
    Line= 
    Line= 
    Line=     local b = 2
    Word= local
    Word= b
    Word= =
    Word= 2
    Line= 
    Line= 
    

    空行出现两次!


    一个方便的函数遍历一个字符串,一次一行,是这样的:

    function getlines (str)
    
      local pos = 0
    
      -- the for loop calls this for every iteration
      -- returning nil terminates the loop
      local function iterator (s)
    
        if not pos then
          return nil
        end -- end of string, exit loop
    
        local oldpos = pos + 1  -- step past previous newline
        pos = string.find (s, "\n", oldpos) -- find next newline
    
        if not pos then  -- no more newlines, return rest of string
          return string.sub (s, oldpos)
        end -- no newline
    
        return string.sub (s, oldpos, pos - 1)
    
      end -- iterator
    
      return iterator, str
    end -- getlines
    

    处理空行。现在您可以像这样编写代码(假设上面的函数在您的代码之前):

    for Paragraph in getlines (code) do
        print("Line=", Paragraph)
        for Word in string.gmatch(Paragraph, "[^ ]+") do        
          print ("Word=", Word)
        end
    end
    

    输出:

    Line=     local a = 1
    Word= local
    Word= a
    Word= =
    Word= 1
    Line= 
    Line=     local b = 2
    Word= local
    Word= b
    Word= =
    Word= 2
    Line= 
    

    制作一个 Lua 模块

    你可以把函数getlines变成一个Lua模块,像这样:

    getlines.lua

    function getlines (str)
    
      local pos = 0
    
      -- the for loop calls this for every iteration
      -- returning nil terminates the loop
      local function iterator (s)
    
        if not pos then
          return nil
        end -- end of string, exit loop
    
        local oldpos = pos + 1  -- step past previous newline
        pos = string.find (s, "\n", oldpos) -- find next newline
    
        if not pos then  -- no more newlines, return rest of string
          return string.sub (s, oldpos)
        end -- no newline
    
        return string.sub (s, oldpos, pos - 1)
    
      end -- iterator
    
      return iterator, str
    end -- getlines
    
    return getlines
    

    现在你所要做的就是“要求”它:

    require "getlines"
    for Paragraph in getlines (code) do
        print("Line=", Paragraph)
        for Word in string.gmatch(Paragraph, "[^ ]+") do        
          print ("Word=", Word)
        end
    end
    

    【讨论】:

      【解决方案2】:

      你没有得到空行,因为你在寻找 \n 的补码。如果您的行中只有 \n,则没有补码,您将找不到匹配项。

      您可以使用以下模式:“[^\n]*\n?”得到你想要的。 此模式匹配任何行。所以所有或没有不是 \n 后面跟着 0 或 1 个 \n

      实例的东西

      【讨论】:

      • 模式[^\n]*\n? 将在末尾(最后一行之后)给出额外的行。
      【解决方案3】:

      这应该可以解决问题:

      local y,code = 0,[[
      
      local a = 123
      
      local b = 456
      
      
      local c = "too much newlines because we're cool"
      ]]
      
      local i = 1
      -- Why would you start with newlines? Oh well
      local sigh = code:match("\n+")
      y = y + #sigh
      -- debug printing of newlines
      for i=1,y do print() end
      while true do
          local start,stop = code:find("[^\n]+",i)
          if not start then break end
          local Paragraph = code:sub(start,stop)
      
          -- Do your Paragraph parsing and stuff
          print("PARAGRAPH:",Paragraph)
      
          start,stop = code:find("\n+",stop+1)
          if not stop then break end
          y,i = y + stop - start + 1,stop+1
          -- printing newlines to get the desired effect in output
          for i=2,stop-start+1 do print() end
          -- starting from 2 since the print(code:sub(...)) already prints one \n
      end
      -- reached end of the string
      

      它为您提供了很好的输出:

      PARAGRAPH:      local a = 123
      
      PARAGRAPH:      local b = 456
      
      
      PARAGRAPH:      local c = "too much newlines because we're cool"
      

      http://www.lua.org/cgi-bin/demo测试

      【讨论】:

        猜你喜欢
        • 2018-03-11
        • 2012-07-07
        • 2021-06-07
        • 2011-03-29
        • 1970-01-01
        • 2014-06-28
        • 1970-01-01
        • 2020-04-06
        • 2013-10-13
        相关资源
        最近更新 更多