【问题标题】:Regex to Select a Sub-Set of a Regex Select正则表达式选择正则表达式选择的子集
【发布时间】:2015-07-23 15:24:38
【问题描述】:

我没有找到任何运气,我相信这是因为我不知道用来解释我正在寻找什么的关键术语。我有以下正则表达式,用于区分一组 HTML 页面上的内部链接和外部链接:

(?<=a href=")[^http](.*?)(\.html")

所以它不会从以下位置选择“http://www.example.com/foo/bar.html”:

<a href="http://www.example.com/foo/bar.html">bar</a>

但会从以下位置选择“/foo/bar.html”:

<a href="/foo/bar.html">bar</a>

这一切都很好。现在我想对选定的字符串“/foo/bar.html”进行子选择以仅隔离“.html”部分。这可能吗?可能带有子字符串或其他向后/向前看?我在这里设置了一个示例:

https://www.regex101.com/r/gZ6bP5/2

这是为了在 Sublime 文本编辑器中进行全局查找/替换。所以我相信我仅限于此的正则表达式。我知道变量查找/替换是可能的,但我无法找到实际操作的示例。

编辑: 澄清一下,我必须区分外部/内部链接的正则表达式效果很好(尽管正如评论者所指出的那样不完美)。问题是关于如何只选择匹配的“.html”部分。

提前致谢!

【问题讨论】:

  • 根据您发布的链接,.html 部分已经通过第二组提供给您。我不是 sublime 用户,但您应该可以通过 /2$2${2} 之类的方式访问它。
  • 从技术上讲,您现有的模式无法按照您描述的方式工作。例如,它不会匹配a href="hello.html",因为它以h 开头。 [^http] 定义了一个字符类,所以它只匹配单个字符。要排除整个字符串的匹配项,您需要一个否定的前瞻(例如(?&lt;=a href=")(?!http)(.*?)(\.html"))。

标签: regex sublimetext2


【解决方案1】:

这似乎可以解决问题:

(?<=a href=")(?!http)[^"]*\/([^"]+)(?=">)

想法:

  • 使用后视(?&lt;=a href=") 确保我们位于链接锚点中。
  • 使用前瞻 (?="&gt;) 确保锚点结束。
  • 使用否定前瞻 (?!http) 确保事情不会以 http 开头。
  • 使用贪婪匹配 [^"]* 捕获直到最后一个斜杠的所有字符,而不跨越引号边界。
  • 在捕获组([^"]+) 中捕获最后一个斜线之后但引号边界之前的所有字符

您可能遇到的问题:

  • 这是有效的 HTML &lt;a target="_blank" href="bob.html"&gt;
  • 这是一个有效的链接&lt;a href="ftp://bob.html"&gt;

虽然您也可以构建正则表达式来处理这些问题。

为了处理目标问题,我们放弃了look-behind和最终look-ahead:

<a[^>]*href="(?!http)[^"]*\/([^"]+)

现在我们匹配一个以&lt;a 开头的字符串,并在其中寻找href="。通过删除(?="&gt;),我们可以处理带有许多标签的锚。

要处理ftp,我们可以这样做:

<a[^>]*href="(?!(http|ftp))[^"]*\/([^"]+)

现在,您可以将字符串的开头包装在一个捕获组中:

(<a[^>]*href="(?!(http|ftp))[^"]*\/)([^"]+)

并根据需要更改$1(文件名.EXTENION 之前的部分)和$2(文件名.EXTENSION)。

一个例子是:https://www.regex101.com/r/gZ6bP5/3

【讨论】:

  • 哇!谢谢你这么彻底的回答。我在其他帖子中看到了变量 $1 和 $2 ,但不理解它们。通过对正在发生的事情的出色分解进行工作,一切都很顺利。我将 1 美元放在“替换”字段中,这正是我想要的。我对您的回答所做的唯一修改是您的正则表达式示例正在选择整个文件名,而不仅仅是文件扩展名。
  • 谢谢,@ideonexus!现在我重新阅读了您的问题,我发现您只是在寻找扩展名。我很抱歉。想必您现在已经知道如何隔离它了?
  • 我做到了!我添加了第二个捕获集(感谢您,我现在知道这是什么)所以:(&lt;a[^&gt;]*href="(?!(http|ftp))[^"]*\/)([^\.]+)([^"]+) 然后在替换字段中我将其设置为 $1$2 以保留除“.html”部分之外的所有内容。效果很好!再次感谢!这真的为我揭开正则表达式的神秘面纱创造了奇迹。
  • 我的荣幸。请注意,如果文件名中有多个句点并且您想要最后一个句点,则使用([^\.]+) 可能会给您带来麻烦,在这种情况下您可以使用(.+\.)([^"]+)。加号运算符会在句号之前再捕获一个字符,并贪婪地消耗到最后一个句号。
猜你喜欢
  • 2011-06-18
  • 2015-01-11
  • 2016-01-11
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多