将POSIX正则表达式移植到Lua模式 - 意外结果

时间:2015-10-01 10:39:12

标签: lua lua-patterns

我很难将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脚本的代码段) 试图进行这种模式匹配:

  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

2 个答案:

答案 0 :(得分:0)

(根据评论更新)当没有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

答案 1 :(得分:0)

  

我在Python中使用了以下模式:pattern=r'name="(.*)" value="(.*)" checked="checked"'它只是起作用。

Python re不符合POSIX,.匹配任何char,但是在那里有一个换行符(在POSIX和Lua中,.匹配任何包含换行符的char。)

如果要匹配一个接一个地具有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