正则表达式 - 如何匹配除特定模式之外的所有内容

Posted

技术标签:

【中文标题】正则表达式 - 如何匹配除特定模式之外的所有内容【英文标题】:Regex - how to match everything except a particular pattern 【发布时间】:2010-10-11 08:16:51 【问题描述】:

如何编写一个正则表达式来匹配任何不符合特定模式的字符串?我遇到了必须匹配(A 和 ~B)模式的情况。

【问题讨论】:

PCRE 最适合这个:参见Regex Pattern to Match, Excluding when… / Except between。我删除了findstr 标签,因为这里的所有答案都对该标签无效。 【参考方案1】:

您可以使用前瞻断言:

(?!999)\d3

此示例匹配除999 之外的三个数字。


但如果您碰巧没有使用此功能的正则表达式实现(请参阅Comparison of Regular Expression Flavors),您可能必须自己构建具有基本功能的正则表达式。

只有基本语法的兼容正则表达式是:

[0-8]\d\d|\d[0-8]\d|\d\d[0-8]

这也匹配任何不是999 的三位数字序列。

【讨论】:

Look-ahead 不是标准的正则表达式语法,它是 Perl 的扩展,只能在 Perl、PCRE (Perl-Compatible RegEx) 或其他非标准实现中工作 它可能不是标准的,但大多数现代语言不支持它吗?目前哪种语言支持前瞻? 确实如此。但大多数正则表达式支持此功能(请参阅 regular-expressions.info/refflavors.html>)。 我认为最后一个正则表达式也不匹配 009、019...等 C 的标准 Lex 不使用 PCRE :-(【参考方案2】:

如果你想匹配一个字符串中的单词 A 而不是匹配单词 B。例如: 如果您有文字:

1. I have a two pets - dog and a cat
2. I have a pet - dog

如果您要搜索 HAVE a dog 表示宠物并且 DOESN'T have cat 的文本行,您可以使用以下正则表达式:

^(?=.*?\bdog\b)((?!cat).)*$

它只会找到第二行:

2. I have a pet - dog

【讨论】:

他在问题中没有提到它,但OP实际上是在使用DOS findstr 命令。它仅提供您期望在正则表达式工具中找到的功能的一小部分;前瞻不在其中。 (我自己刚刚添加了findstr 标签。) 嗯,是的,我现在在他的帖子中发现了一个 cmets。我在标题中看到了正则表达式。无论如何,如果有人在搜索相同的正则表达式时发现这篇文章,就像我一样,也许它可能对某人有帮助:) 感谢 cmets【参考方案3】:

匹配模式并使用宿主语言反转匹配的布尔结果。这将更加清晰和可维护。

【讨论】:

然后我只得到 (~A or B) 而不是 (A and ~B)。它不能解决我的问题。 伪代码:字符串 toTest; if (toTest.matches(A) AND !toTest.matches(B)) ... 我应该更清楚一点——这些片段并不完全独立。如果 A 匹配字符串的一部分,那么我们关心 ~B 是否匹配它的其余部分(但不一定是全部)。这是针对 windows 命令行 findstr 函数的,我发现它仅限于真正的正则表达式,所以没有实际意义。【参考方案4】:

不是,复活这个古老的问题,因为它有一个没有提到的简单解决方案。 (在为regex bounty quest 做一些研究时发现了你的问题。)

我面临必须匹配 (A 和 ~B) 的情况 模式。

基本的正则表达式非常简单:B|(A)

您只需忽略整体匹配并检查包含 A 的第 1 组捕获。

一个例子(包含所有关于在正则表达式中解析 html 的免责声明):A 是数字,B 是 <a tag 中的数字

正则表达式:<a.*?<\/a>|(\d+)

Demo(查看右下窗格中的第 1 组)

参考

How to match pattern except in situations s1, s2, s3

How to match a pattern unless...

【讨论】:

这听起来好得令人难以置信!不幸的是,这个解决方案并不通用,并且在 Emacs 中失败了,即使在将 \d 替换为 [[:digit:]] 之后也是如此。 The first reference 提到它特定于 Perl 和 php:“使用特定于 Perl 和 PHP 的语法的变体可以实现相同的功能。”【参考方案5】:

正则语言的补语也是正则语言,但要构造它,您必须为正则语言构建DFA,并将任何有效状态更改为错误。有关示例,请参阅this。该页面没有说的是它将/(ac|bd)/转换为/(a[^c]?|b[^d]?|[^ab])/。从 DFA 转换回正则表达式并非易事。如果您可以像之前建议的那样使用不变的正则表达式并更改代码中的语义,那就更容易了。

【讨论】:

如果我正在处理实际的正则表达式,那么这一切都没有实际意义。正则表达式现在似乎指的是大多数语言支持的模式匹配的模糊 CSG-ish (?) 空间。由于我需要匹配(A 和 ~B),因此无法删除否定并仍然一步完成。 Lookahead,如上所述,如果 findstr 做的事情超出了真正的 DFA 正则表达式,就会做到这一点。整个事情有点奇怪,我不知道为什么我必须这样做命令行(现在批处理)风格。这只是我双手被绑的另一个例子。 @notnot:您正在使用 Windows 中的 findstr?然后你只需要/v。喜欢:findstr 一个输入文件 | findstr /v B > outputfile.txt 第一个匹配所有有A的行,第二个匹配所有没有B的行。 谢谢!这实际上正是我所需要的。不过,我并没有那样问这个问题,所以我仍然把答案交给 Gumbo 以获得更笼统的答案。【参考方案6】:

模式 - 重新

str.split(/re/g) 

将返回除模式之外的所有内容。

测试here

【讨论】:

您可能想提一下您需要再次加入。 类似的方法是使用replacestr.replace(/re/g, ''),则无需重新加入它们。如果你在一个漂亮的尾随 \s 中加入?像str.replace(/\re\s?/g, '') 这样你就可以摆脱在字符串中间被替换的任何重复空格【参考方案7】:

我在这里的回答也可能解决你的问题:

https://***.com/a/27967674/543814

您可以使用 Match,而不是 Replace。 您将阅读组$2,而不是组$1$2 组在此处设置为非捕获,您可以避免这种情况。

例子:

Regex.Match("50% of 50% is 25%", "(\d+\%)|(.+?)");

第一个捕获组指定您希望避免的模式。最后一个捕获组捕获其他所有内容。只需读出该组,$2

【讨论】:

【参考方案8】:
(B)|(A)

然后使用第 2 组捕获的内容...

【讨论】:

他需要捕获而不是B,他的目标不是忽略所有B模式。

以上是关于正则表达式 - 如何匹配除特定模式之外的所有内容的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式:匹配除一个单词之外的所有内容[重复]

正则表达式:匹配文本段落中除特定短语外的所有内容

正则表达式匹配除特定路径之外的所有https URL

如何使用正则表达式选择除捕获组之外的所有内容?

正则表达式,匹配除 \r \n 之外的所有内容作为普通字符

linux:正则表达式