【问题标题】:Python regex not to match http://Python 正则表达式不匹配 http://
【发布时间】:2011-07-28 13:31:11
【问题描述】:

我遇到了匹配和替换某些不包含在 http:// 中的单词的问题

当前正则表达式:

 http://.*?\s+

这匹配模式http://www.egg1.com @987654321@

我需要一个正则表达式来匹配包含在 http:// 之外的某些单词

例子:

"This is a sample. http://www.egg1.com and http://egg2.com. This regex will only match 
 this egg1 and egg2 and not the others contained inside http:// "

 Match: egg1 egg2

 Replaced: replaced1 replaced2

最终输出:

 "This is a sample. http://www.egg1.com and http://egg2.com. This regex will only 
  match this replaced1 and replaced2 and not the others contained inside http:// "

问题: 需要匹配某些模式(例如:egg1 egg2),除非它们是 http:// 的一部分。如果 egg1 和 egg2 存在于 http:// 中,则不匹配它们

【问题讨论】:

  • 换句话说:您想要匹配某些模式(在您的示例中为 egg1 和 egg2)除非它们是URL 的一部分?
  • 您陈述问题的方式并不重要,匹配是否来自 URL。你真正想要匹配的是什么?
  • @Ferdinand 是的..你是对的.. 如果 egg1 和 egg2 在 http:// 内,则不匹配。
  • 他想在“Google 可以在http://www.google.com”中找到“Google”,跳过网址中的“google”。
  • http:// 之后的文本没有“包含在其中”。

标签: python regex regex-negation


【解决方案1】:

我能想到的一个解决方案是为 HTTP-URL 和您的模式形成一个组合模式,然后相应地过滤匹配项:

import re

t = "http://www.egg1.com http://egg2.com egg3 egg4"

p = re.compile('(http://\S+)|(egg\d)')
for url, egg in p.findall(t):
  if egg:
    print egg

打印:

鸡蛋3 蛋4

更新:要将此习惯用法与re.sub() 一起使用,只需提供一个过滤器函数:

p = re.compile(r'(http://\S+)|(egg(\d+))')

def repl(match):
    if match.group(2):
        return 'spam{0}'.format(match.group(3))
    return match.group(0)

print p.sub(repl, t)

打印:

http://www.egg1.com http://egg2.com 垃圾邮件3 垃圾邮件4

【讨论】:

  • 由于我将使用 re.sub 来替换匹配的单词,我可以像你使用 re.sub 那样做吗?
  • @Ferdinana 是否可以将过滤器功能与匹配的组一起使用(如 spam1 spam2)..更新有问题..
  • 是的,当然。您可以在过滤器功能中做任何您喜欢的事情,并且您可以在正则表达式中嵌套分组括号。我相应地更新了我的答案。我想从这里你可以自己解决?
【解决方案2】:

这不会捕获http://...:

(?:http://.*?\s+)|(egg1)

【讨论】:

  • 您应该提到它需要使用group(1) 才能获得正确的值,并且它仍会返回匹配的URL,只是组1 的值是None。
  • @JAB 是的,你是对的。我只是假设他知道一般的正则表达式是如何工作的:)
【解决方案3】:

你需要在你的模式前面加上一个否定的lookbehind断言:

(?<!http://)egg[0-9]

在这个正则表达式中,每当正则表达式引擎找到匹配egg[0-9] 的模式时,它都会回过头来验证前面的模式是否不匹配 http://。否定的lookbehind 断言以(?&lt;! 开头,以) 结尾。这些分隔符之间的所有内容都不应位于以下模式之前,并且不会包含在结果中。

如何在你的情况下使用它:

>>> regex = re.compile('(?<!http://)egg[0-9]')
>>> a = "Example: http://egg1.com egg2 http://egg3.com egg4foo"
>>> regex.findall(a)
['egg2', 'egg4']

【讨论】:

  • @Ferdinand 是的,你是对的。显然,后向断言不是这项工作的正确工具:)
【解决方案4】:

扩展brandizzi的答案,我只需将他的正则表达式更改为:

(?<!http://[\w\._-]*)(egg1|egg2)

【讨论】:

  • 这是一个陷阱:后视需要固定宽度的模式,因此您的示例无法编译。
  • 你试过这个吗? sre_constants.error: look-behind requires fixed-width pattern.
  • 我的错,我用 .Net 正则表达式实用程序尝试了它,而不是 Python 的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-29
  • 2016-07-01
  • 2013-09-22
  • 1970-01-01
  • 2022-12-11
  • 2011-07-09
相关资源
最近更新 更多