将 POSIX 正则表达式移植到 Lua 模式 - 意外结果
我正在尝试将 POSIX regex 移植到 Lua 字符串模式中,但遇到了困难。
我正在处理 HTML 响应,我想要过滤已选中的复选框。我特别关注每个已选中的复选框的“value”和“name”字段:
以下是我感兴趣的复选框示例:
<input class="rid-2 form-checkbox" id="edit-2-access-comments" name="2[access comments]" value="access comments" checked="checked" type="checkbox">
<input class="rid-3 form-checkbox real-checkbox" id="edit-3-administer-comments" name="3[administer comments]" value="administer comments" checked="checked" type="checkbox">
相反,我不感兴趣的是这种(未选中的)复选框:
<input class="rid-2 form-checkbox" id="edit-2-access-printer-friendly-version" name="2[access printer-friendly version]" value="access printer-friendly version" type="checkbox">
使用 POSIX regex,在 Python 中我使用了以下模式:pattern=r'name="(.*)" value="(.*)" checked="checked"',这个方法很有效。
我的第一个尝试是在 Lua 中简单使用以下模式:pattern ='name="(.-)" value="(.-)" checked="checked"',但这导致奇怪的结果(第一个捕获了预期的内容,但第二个捕获了大量不需要的 HTML)。
我还尝试了以下模式:
pattern = 'name="(%d?%[.-%])" value="(.-)"%s?(c?).-="?c.-"%s?type="checkbox"'
这一次,“value”的内容在第二个捕获中返回,但所有复选框都匹配了(而不仅仅是那些具有“checked =“checked””字段的复选框)。
为了完整起见,这里是我的 Lua 代码(来自我的 Nmap NSE 脚本),试图进行这种模式匹配:
pattern = 'name="(.-)" value="(.-)" checked="checked"'
data = {}
for name, value in string.gmatch(res.body, pattern) do
stdnse.debug(1, string.format("%s %s", name, value))
end
我已经在Python中使用了以下模式:pattern=r'name="(.*)" value="(.*)" checked="checked"',它可以正常工作。
Python的re不符合POSIX规范,.匹配除换行符以外的任何字符(在POSIX和Lua中,.匹配包括换行符在内的任何字符)。
如果您想匹配依次具有上述3个属性的字符串,则应使用类似以下内容的内容:
local pattern = 'name="([^"]*)"%s+value="([^"]*)"%s+checked="checked"'
为什么不使用[^\r\n]-?因为如果一行中有两个标记,第一个标记具有第一个和/或第二个属性,第二个标记具有第二个和第三个属性或仅具有第二个属性(即使第三个标记具有第三个属性,而第一个标记包含前两个属性),则将有匹配,因为[^\r\n]匹配<和>,并且可以跨越标记“过火”。
注意,否定的括号表达式[^"]*只会匹配除 "以外的 0 或 多个字符,从而限制匹配在一个标记中。
请参阅Lua demo:
local rx = 'name="([^"]*)"%s+value="([^"]*)"%s+checked="checked"'
local s = '<li name="n1"\nvalue="v1"><li name="n2"\nvalue="v1" checked="checked"><li name="n3"\nvalue="v3" checked="checked">'
for name, value in string.gmatch(s, rx) do
print(name, value)
end
输出:
n2 v1
n3 v3
- 如何将两个不同的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 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
更新基于评论
当输入中存在一个不带
checked="checked"的行在一个带该属性的行之前时,.-表达式会捕获不必要的部分,因而无法匹配成功。有几种避免这种情况的方法。@EgorSkriptunoff 提出了一种方法,即使用([^"]*)作为匹配模式;另一种方法是排除新的行([^\r\n]-)。以下示例将会按你的预期输出结果:local s = [[ <input class="rid-2 form-checkbox" id="edit-2-access-comments" name="2[access comments]" value="access comments" checked="checked" type="checkbox"> <input class="rid-2 form-checkbox" id="edit-2-access-printer-friendly-version" name="2[access printer-friendly version]" value="access printer-friendly version" type="checkbox"> <input class="rid-3 form-checkbox real-checkbox" id="edit-3-administer-comments" name="3[administer comments]" value="administer comments" checked="checked" type="checkbox"> ]] local pattern = 'name="([^\r\n]-)" value="([^\r\n]-)" checked="checked"' for name, value in string.gmatch(s, pattern) do print(name, value) end输出结果: