Lua字符串模式

时间:2016-02-06 21:20:06

标签: lua

这是我的代码:

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

3 个答案:

答案 0 :(得分:1)

你没有得到空行,因为你找到\ n的补码。如果你的行中只有\ n,则没有补充,你就没有匹配。

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

的实例

答案 1 :(得分: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

现在你所要做的就是&#34;要求&#34;它:

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

答案 2 :(得分:0)

这应该可以解决问题:

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

进行测试