迭代包括空白行在内的所有行。
2013-10-11 20:14:41
收藏:0
阅读:214
评论:6
给出一个带有一些空行的多行字符串,如何在 Lua 中迭代行,包括空行?
local s = "foo\nbar\n\njim"
for line in magiclines(s) do
print( line=="" and "(blank)" or line)
end
--> foo
--> bar
--> (blank)
--> jim
这段代码不包括空行:
for line in string.gmatch(s,'[^\r\n]+') do print(line) end
--> foo
--> bar
--> jim
这段代码包括多余的空行:
for line in string.gmatch(s,"[^\r\n]*") do
print( line=="" and "(blank)" or line)
end
--> foo
--> (blank)
--> bar
--> (blank)
--> (blank)
--> jim
--> (blank)
点赞
用户415823
以下模式应匹配每行,包括空行,只有一个限制条件:字符串必须包含终止的 CR 或 LF。
local s = "foo\nbar\n\njim\n" -- added terminating \n
for line in s:gmatch("([^\r\n]*)[\r\n]") do
print(line == "" and "(blank)" or line)
end
--> foo
--> bar
--> (blank)
--> jim
一个替代模式,不需要额外的 CR 或 LF,将产生一个空白行作为最后一行(因为捕获没有东西是可以接受的)。
local s = "foo\nbar\n\njim"
for line in s:gmatch("([^\r\n]*)[\r\n]?") do
print(line == "" and "(blank)" or line)
end
--> foo
--> bar
--> (blank)
--> jim
--> (blank)
2013-10-11 21:42:55
用户107090
尝试一下:
function magiclines(s)
如果s:sub(-1)~="\n" then s=s.."\n" end
返回 s:gmatch("(.-)\n")
end
2013-10-12 01:40:41
用户441830
以下是一个使用 LPEG 的解决方案:
local lpeg = require "lpeg"
local lpegmatch = lpeg.match
local P, C = lpeg.P, lpeg.C
local iterlines
do
local eol = P"\r\n" + P"\n\r" + P"\n" + P"\r"
local line = (1 - eol)^0
iterlines = function (str, f)
local lines = ((line / f) * eol)^0 * (line / f)
return lpegmatch (lines, str)
end
end
你得到的是一个可以替代迭代器的函数。第一个参数是你想迭代的字符串,第二个参数是每个匹配的操作:
--- 打印每一行
iterlines ("foo\nbar\n\njim\n\r\r\nbaz\rfoo\n\nbuzz\n\n\n\n", print)
--- 在 printf 的同时计数行数
local n = 0
iterlines ("foo\nbar\nbaz", function (line)
n = n + 1
io.write (string.format ("[%2d][%s]\n", n, line))
end)
2013-10-12 12:13:26
用户1244588
这里是另一种lPeg的解决方案,因为似乎我和phg在同时进行。但是由于语法更美观,我仍然会给你!
local lpeg = require "lpeg"
local C, V, P = lpeg.C, lpeg.V, lpeg.P
local g = P({ "S",
S = (C(V("C")^0) * V("N"))^0 * C(V("C")^0),
C = 1 - V("N"),
N = P("\r\n") + "\n\r" + "\n" + "\r",
})
像这样使用它:
local test = "Foo\n\nBar\rfoo\r\n\n\n\rbar"
for k,v in pairs({g:match(test)}) do
print(">", v);
end
或者当然,只需print(g:match(test))
2013-10-12 12:30:44
用户19843756
- 遍历
text中的所有项,使用方法如下:- 选项:
separator = "pattern string",默认值为\nplain = boolean,默认值为nil,用于string.findno_item = anything,默认值为nil,它是前一项和后一项的返回值 [1] 和 [last]
- 选项:
- 对于
TextIterator(s, { options })中的每一个项和状态,使用以下方式:item- 不包括分隔符的内容state.item_num- 从 1 开始的项数state.previous_item- 前面的项state.next_item- 后面的项state.separator- 匹配的分隔符state.is_last- 是否是最后一项
local function TextIterator(s, options)
local options = options or {}
local state = {text = s, begin=1, next_begin=1,
item_num=-1, next_item=options.no_item, is_last=false}
local function get_item(state)
local text = state.text
state.begin = state.next_begin
state.previous_item = state.item
state.item = state.next_item
state.separator = state.next_separator
state.item_num = state.item_num + 1
if state.begin == -1 then
state.next_item = options.no_item
state.next_begin = -2
state.is_last = true
return state.item, state
elseif state.begin == -2 then
return nil
end
local b, e = text:find(options.separator,
state.next_begin, options.plain)
if b then
if options.plain then
state.next_separator = options.separator
else
state.next_separator = string.match(text,
"("..options.separator..")", state.next_begin)
end
state.next_begin = e+1
state.next_item = text:sub(state.begin,
e-string.len(state.next_separator))
return state.item, state
else
state.next_separator = ""
state.next_begin = -1
state.next_item = text:sub(state.begin)
return state.item, state
end
end
if not options.separator then options.separator = "\n" end
get_item(state) -- 初始化
return get_item, state
end
txt = "a,b;c.d/e.f.g"
for item, state in TextIterator(txt, { separator="%p", plain=false, no_item=nil }) do
print(item, state.item_num, state.separator,
state.previous_item, state.next_item, state.is_last)
end
>lua -e "io.stdout:setvbuf 'no'" "txtiterator.lua"
a 1 , nil b false
b 2 ; a c false
c 3 . b d false
d 4 / c e false
e 5 . d f false
f 6 . e g false
g 7 f nil true
>Exit code: 0
2022-08-25 08:22:05
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

让我们看看这个
magiclines的实现是否符合你的要求:local function magiclines( str ) local pos = 1; return function() if not pos then return nil end local p1, p2 = string.find( str, "\r?\n", pos ) local line if p1 then line = str:sub( pos, p1 - 1 ) pos = p2 + 1 else line = str:sub( pos ) pos = nil end return line end end你可以用以下代码测试它:
local text = [[ foo bar jim woof ]] for line in magiclines( text ) do print( line=="" and "(blank)" or line) end输出:
foo bar (blank) jim (blank) woof (blank)