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

而不是:

--空格
local a = 1
--空格
local b = 2
--空格
点赞
用户5352026
用户5352026

这应该能行:

local y,code = 0,[[
local a = 123

local b = 456

local c = "too much newlines because we're cool"
]]

local i = 1
-- 为什么要从新行开始?好吧
local sigh = code:match("\n+")
y = y + #sigh
-- 调试打印新行
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)

    -- 处理并解析段落
    print("PARAGRAPH:",Paragraph)

    start,stop = code:find("\n+",stop+1)
    if not stop then break end
    y,i = y + stop - start + 1,stop+1
    -- 打印新行以获得所需的输出效果
    for i=2,stop-start+1 do print() end
    -- 从2开始,因为print(code:sub(...))已经打印了一个\n
end
-- 到达字符串结尾

它会给你一个好看的输出结果:

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上测试过。

2016-02-06 21:45:17
用户2858170
用户2858170

你没有得到空行是因为你寻找了\n的补集。如果你的行中只有\n,那么就没有补集,你就得不到匹配。

你可以使用这个模式:"\[^\n\]*\\n?" 来获得你想要的。这个模式匹配任何行。因此,任何不是\n且后跟0或1个实例的\n的东西或什么都不是

2016-02-06 21:56:13
用户5043289
用户5043289

你不会得到第一个空格因为 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”它:

require "getlines"
for Paragraph in getlines (code) do
    print("Line=", Paragraph)
    for Word in string.gmatch(Paragraph, "[^ ]+") do
      print ("Word=", Word)
    end
end
2016-02-06 22:12:17