【语法算法】
string.find 的起始偏移就这一行:
local start, endPos = string.find(str, pattern, init)
第三个参数 init 是搜索的起始偏移——从字符串的第 init 个字符开始搜索——string.find 的全部机制就这一行。可这一行的妙处在于:起始偏移让"在长字符串中多次搜索不同模式"变成了一行代码——每次传入上一次的结束位置加一,就能从前一次结束的地方继续搜索。今天拆开。
一、全搜、偏移、循环三段
string.find 的三段。全搜:不传起始偏移——从字符串第一个字符开始搜索——返回匹配的起始和结束位置——没找到返回 nil。偏移:传入起始偏移——从指定位置开始搜索——起始偏移让"在长文本中多次搜索"变成可能——每次传入上一次的结束位置加一。循环:配合 while 循环可以遍历所有匹配——每次搜索完更新起始偏移——直到返回 nil 终止——这就是手动版的 gmatch。三段连起来:string.find 玩的是"搜索范围的控制"——起始偏移是搜索的"起点指针",每次搜索后移动指针就能遍历所有匹配。
graph TD
A["find(str, pat, 1)"] --> B["返回 s1, e1"]
B --> C["find(str, pat, e1+1)"]
C --> D["返回 s2, e2"]
D --> E["find(str, pat, e2+1)"]
E --> F["返回nil, 遍历结束"]
二、偏移搜索的正确写法
local str = "name=John; age=25; city=NYP"
local init = 1
while true do
local s, e = string.find(str, "%w+", init)
if not s then break end
local match = string.sub(str, s, e)
print("匹配:", match, "位置:", s, "-", e)
init = e + 1
end
init = e + 1 是循环推进的关键——上一次匹配的结束位置加一就是下一次搜索的起始——不推进的话 find 会永远找到同一个匹配——死循环。
三、偏移的纪律和裸匹配的开关
起始偏移的纪律是"只进不退":搜索偏移必须大于上一次的结束位置——往回搜会造成无限循环——往回搜也会导致重复匹配——偏移只进不退是搜索循环的铁律。plain 参数是另一个容易被忽略的开关:string.find 的第四个参数设为 true 表示关闭模式匹配——纯文本搜索——模式中的 % 和特殊字符按字面意思匹配——纯文本搜索比模式搜索快。和 gmatch 的分账写清楚:gmatch 内部就是循环调 find——gmatch 是 find 的语法糖——但 gmatch 返回的是匹配内容而不是位置——需要位置信息时用 find,需要内容时用 gmatch——两者的选择取决于你需要"在哪"还是"是什么"。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【游戏功能】 上一版藏了条只在长战斗里露头的隐蔽报错:吞劲的计数器跨场不清零——第一场怪喂满了五拳把它噎住,第二场新怪刚出手…
【游戏功能】 再抛一个坑:血条的长短是天生的吗?一只怪的命根子一千点,打完就满,下回见面还是一千点——命根是它自己的,跟你的…
【游戏功能】 var over=d-before ——先拆这一行。刀额减去落刀前的血,多出来的那一截就是杀过头的余劲。顺劈纹…
【游戏功能】 上一轮的线上事故出得难看:有玩家押了二十滴血没在限期内斩掉怪,注被纹收走了,直接在频道里喊"强买强卖"。复盘下…
【游戏功能】 上一版留了个查了半天的隐蔽报错:战斗统计里玩家的出招间隔写着一秒四,实际手感却是一秒整——两套计时账对不上,运…
【游戏功能】 先抛一个坑:你砍出去的最强一刀,去哪了?暴击三千的天胡刀,数字蹦完就散,下一刀又是从零起算——最强的那一击在战…