【问题标题】:How to get the inverse of a regular expression?如何获得正则表达式的逆?
【发布时间】:2009-07-17 01:04:17
【问题描述】:

假设我有一个正则表达式,可以正常工作以查找文本文件中的所有 URL:

(http://)([a-zA-Z0-9\/\.])*

如果我想要的不是 URL 而是相反的 - 除了 URL 之外的所有其他文本 - 是否有一个简单的修改可以得到这个?

【问题讨论】:

标签: regex regex-negation inverse


【解决方案1】:

您可以简单地搜索并用空字符串替换与正则表达式匹配的所有内容,例如在 Perl s/(http:\/\/)([a-zA-Z0-9\/\.])*//g

这将为您提供原始文本中的所有内容,除了那些与正则表达式匹配的子字符串。

【讨论】:

  • 所以在替换所有匹配项后,如果测试字符串的长度不为零,那么您的反转正则表达式为真。这正是我需要的逻辑,而不是构建反向正则表达式。谢谢 dmcer :)
【解决方案2】:

如果出于某种原因您需要纯正则表达式解决方案,请尝试以下操作:

((?<=http://[a-zA-Z0-9\/\.#?/%]+(?=[^a-zA-Z0-9\/\.#?/%]))|\A(?!http://[a-zA-Z0-9\/\.#?/%])).+?((?=http://[a-zA-Z0-9\/\.#?/%])|\Z)

我稍微扩展了一组 URL 字符 ([a-zA-Z0-9\/\.#?/%]) 以包括一些重要的字符,但这绝不意味着准确或详尽。

正则表达式有点像怪物,所以我会尝试分解它:

(?<=http://[a-zA-Z0-9\/\.#?/%]+(?=[^a-zA-Z0-9\/\.#?/%])

第一个药水匹配 URL 的结尾。 http://[a-zA-Z0-9\/\.#?/%]+ 匹配 URL 本身,而 (?=[^a-zA-Z0-9\/\.#?/%]) 断言 URL 后面必须跟一个非 URL 字符,以便我们确定我们在末尾。使用前瞻,以便寻找但不捕获非 URL 字符。整个事情被包裹在一个lookbehind (?&lt;=...) 中,以寻找它作为匹配的边界,同样没有捕获该部分。

我们还想在文件的开头匹配一个非 URL。 \A(?!http://[a-zA-Z0-9\/\.#?/%]) 匹配文件的开头 (\A),后跟一个否定的前瞻,以确保文件开头没有潜伏的 URL。 (这个 URL 检查比第一个更简单,因为我们只需要 URL 的开头,而不是整个内容。)

这两项检查都放在括号中,OR'd 与 | 字符一起。之后,.+? 匹配我们试图捕获的字符串。

然后我们来到((?=http://[a-zA-Z0-9\/\.#?/%])|\Z)。在这里,我们检查 URL 的开头,再次使用 (?=http://[a-zA-Z0-9\/\.#?/%])。文件的结尾也是一个很好的迹象,表明我们已经到了比赛的结尾,所以我们也应该使用\Z 来寻找它。与第一个大组类似,我们将其括在括号中并将OR 两种可能性放在一起。

| 符号需要括号,因为它的优先级很低,所以你必须明确说明OR 的边界。

这个正则表达式严重依赖于零宽度断言(\A\Z 锚点,以及环视组)。在将正则表达式用于任何严重或永久性的事情之前,您应该始终了解它(否则您可能会遇到 perl 的情况),因此您可能需要查看 Start of String and End of String AnchorsLookahead and Lookbehind Zero-Width Assertions

当然欢迎指正!

【讨论】:

  • 我看到您将此作为已接受的答案。谢谢!不过,我想重申我对复杂正则表达式的警告。如果您或其他人稍后要阅读代码,请做好记录。此外, [a-zA-Z0-9\/\.#?/%] 可以更改为 [a-zA-Z0-9/.#?%] - 您(通常)不需要转义符号在一个字符组内。您可能还想尝试 https?:// 而不是 http://,也可能还想尝试其他协议,具体取决于您的要求。按照 superjadex12 的建议,不要忘记查看 regular-expressions.info
【解决方案3】:

如果我正确理解了这个问题,您可以使用搜索/替换...在您的表达式周围使用通配符,然后替换第一个和最后一个部分。

s/^(.*)(your regex here)(.*)$/$1$3/

【讨论】:

  • 那只会删除一个匹配:最后一个。而且效率也很低。
【解决方案4】:

我不确定这是否会完全按照您的预期工作,但它可能会有所帮助: 无论您放在括号 [] 中的任何内容都将匹配。如果您将 ^ 放在括号内,即 [^a-zA-Z0-9/.] 它将匹配所有除了括号中的内容。

http://www.regular-expressions.info/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多