【问题标题】:Porting POSIX regex to Lua pattern - unexpected results将 POSIX 正则表达式移植到 Lua 模式 - 意外结果
【发布时间】:2015-12-29 09:11:19
【问题描述】:

我很难将 POSIX 正则表达式移植到 Lua 字符串模式。

我正在处理我想从中过滤复选框的 html 响应 被检查。特别是我对valuename 的字段感兴趣 每个选中的复选框:

以下是我感兴趣的复选框示例:

<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 正则表达式,我在 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 脚本的 sn-p) 尝试进行这种模式匹配:

  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

【问题讨论】:

  • pattern = 'name="([^"]*)" value="([^"]*)" checked="checked"'
  • 感谢 Egor,它现在可以完美运行了。

标签: lua lua-patterns


【解决方案1】:

(根据 cmets 更新)当没有 checked="checked" 的行位于输入中带有 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

输出:

2[access comments]  access comments
3[administer comments]  administer comments

【讨论】:

  • 如果第一项未选中(没有checked="checked")并且第二项被选中,您将看到问题。
  • 对;那么正如@EgorSkriptunoff 之前建议的那样,需要在模式中禁止新行或引号。
【解决方案2】:

我在 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] 匹配 &lt;&gt; 并且可以跨标签“过火”。

请注意,[^"]* 是一个否定的括号表达式,它只会匹配除 " 之外的 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多