正则表达式排除所有与负前瞻匹配的组

Regex excluding all groups matched by negative lookahead

我有一个正则表达式来解析 HTML 代码块中的文件夹和文件名,并排除扩展名为 .ini.

的文件名

我当前的正则表达式:/href="([\w]+)(\.[\w]+)*/ig

  1. 匹配第一组:1+个单词字符
  2. 匹配第二组 0+ 次:. 然后 1+ 个单词字符
  3. 标志:不区分大小写并且尽可能多地匹配

我曾尝试一次又一次地使用否定前瞻(我认为是正确的解决方案)来删除扩展名为 .ini 的匹配项。可悲的是,我的使命失败了,我就在这里。我选择不包括上面的尝试,因为它只会污染问题


来自全网阅读:

重述:

我能弄清楚如何只忽略 .ini 组,但无法弄清楚如何让正则表达式忽略所有组。你能帮我找出正确的正则表达式吗?


示例输入字符串

我用来测试正则表达式的 HTML 代码示例块。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
 <head>
  <title>Index of /images/AAVS</title>
 </head>
 <body>
<h1>Index of /images/AAVS</h1>
  <table>
   <tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
   <tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/images/">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="20190823/">20190823/</a>              </td><td align="right">2019-09-19 19:37  </td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="20190826/">20190826/</a>              </td><td align="right">2019-09-19 19:31  </td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[   ]"></td><td><a href="desktop.ini">desktop.ini</a>            </td><td align="right">2019-09-19 19:24  </td><td align="right">136 </td><td>&nbsp;</td></tr>
   <tr><th colspan="5"><hr></th></tr>
</table>
</body></html>

此外,我想说我确信有更好的方法。欢迎大家批评指正!

正则表达式是 (?<=href=")[^"]+(?<!\.ini)(?=")

  1. (?<=href=") href="
  2. 的正面回顾
  3. [^"]+ 匹配尽可能多的非双引号字符
  4. (?<!\.ini) .ini
  5. 的负面回顾
  6. (?=") 双引号的正向超前

代码:

import re

html = """<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
 <head>
  <title>Index of /images/AAVS</title>
 </head>
 <body>
<h1>Index of /images/AAVS</h1>
  <table>
   <tr><th valign="top"><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr>
   <tr><th colspan="5"><hr></th></tr>
<tr><td valign="top"><img src="/icons/back.gif" alt="[PARENTDIR]"></td><td><a href="/images/">Parent Directory</a>       </td><td>&nbsp;</td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="20190823/">20190823/</a>              </td><td align="right">2019-09-19 19:37  </td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="20190826/">20190826/</a>              </td><td align="right">2019-09-19 19:31  </td><td align="right">  - </td><td>&nbsp;</td></tr>
<tr><td valign="top"><img src="/icons/unknown.gif" alt="[   ]"></td><td><a href="desktop.ini">desktop.ini</a>            </td><td align="right">2019-09-19 19:24  </td><td align="right">136 </td><td>&nbsp;</td></tr>
   <tr><th colspan="5"><hr></th></tr>
</table>
</body></html>"""

l = re.findall(r'(?<=href=")[^"]+(?<!\.ini)(?=")', html, flags=re.I)
print(l)

打印:

['?C=N;O=D', '?C=M;O=A', '?C=S;O=A', '?C=D;O=A', '/images/', '20190823/', '20190826/']

上述正则表达式将接受任何 href 值,这就是它返回 '?C=N;O=D' 等值的原因。如果您希望将其限制为组成您专门查找的文件和文件夹名称的值,您可以使用限制性更强的正则表达式,例如:

(?<=href=")[a-z0-9_./-]+(?<!\.ini)(?=")

这将导致打印:

['/images/', '20190823/', '20190826/']

但是,事实上,根据我的研究,?C=N;O=D 将是 Linux 文件系统中的合法文件名。

您甚至可以在不使用后瞻或前瞻的情况下完成任务:

l = [m.group(1) for m in re.finditer(r'(?:href=")([^"]+)(?:")', html, flags=re.I) if not m.group(1).lower().endswith(".ini")]