如何排除特定的字符串常量?

188

正则表达式是否可以用来匹配除特定字符串常量(如"ABC")之外的任何字符串?

有没有可能仅排除一个特定的字符串常量?


1
你使用哪个工具?根据工具的不同,可能会有一种方法可以在正则表达式外部指定。例如,grep支持-v选项来反转匹配的意义。 - Will Bickford
所以你想匹配给定字符串的每个字符,除了其中的ABC部分?换句话说,“A string with ABC”将匹配“A string with”。 - Steve Wortham
5个回答

204

你需要使用负向前瞻断言。

(?!^ABC$)
你可以例如使用以下内容。
(?!^ABC$)(^.*$)

如果这在你的编辑器中不起作用,请尝试以下方法。它已经在Ruby和JavaScript中测试过:

^((?!ABC).)*$

3
如果您要查找不包含ABC的字符串,这将起作用。但这是目标吗?还是目标是匹配除了ABC之外的每个字符? - Steve Wortham
谢谢你指出这个问题,你是对的 - 我的建议只是避免以ABC开头的字符串 - 我忘记了锚定断言。我会纠正这个错误。 - Daniel Brückner
5
我觉得这很清楚明确——“任何字符串,除了一个特定的字符串 [常量]”,因此除了 ABC 本身之外,包括包含 ABC 的任何字符串。 - Daniel Brückner
你只使用了断言,但忘记了匹配表达式 - 使用 (?!^ABC$)(^.*$) 就可以了。 - Daniel Brückner
7
最近我帮一个朋友做了类似的事情。但他不想匹配包含在字符串中的任何子字符串。所以我稍微修改了你的表达式*(?!.ABC)^.$*,这个方法非常有效。 - Steve Wortham
显示剩余3条评论

9
在.NET中,您可以像这样利用分组:

http://regexhero.net/tester/?id=65b32601-2326-4ece-912b-6dcefd883f31

你会注意到:

(ABC)|(.)

将获取第二组中除了ABC以外的所有内容。每个组都用括号括起来。因此,(ABC)是第1组,(.)是第2组。

因此,在替换中只需获取第2组:

$2

在.NET中,您可以查看Regex类中的Groups集合以获得更多控制。在大多数其他正则表达式实现中,您也应该能够做类似的事情。
更新:我在这里找到了一种更快的方法: http://regexhero.net/tester/?id=997ce4a2-878c-41f2-9d28-34e0c5080e03 它仍然使用分组(我找不到不使用分组的方法)。但是,这种方法比第一个方法快10倍以上。

8

除非您的正则表达式引擎具有特殊支持,否则这并不容易。最简单的方法是使用负匹配选项,例如:

$var !~ /^foo$/
    or die "too much foo";

如果不是这样,你就必须做出一些邪恶的事情:
$var =~ /^(($)|([^f].*)|(f[^o].*)|(fo[^o].*)|(foo.+))$/
    or die "too much foo";

这段代码的意思是:"如果字符串首字母不是f,那么后面的字符可以是任何字符;如果字符串首字母是f,但第二个字母不是o,那么后面的字符也可以是任何字符;否则,如果字符串以fo开头,那么下一个字符不能是o。"


这不允许空字符串,ffofoo - Gumbo
1
@Gumbo:它可以很好地接受空字符串;请注意,($)是第一个备选项,因此^$(空字符串)被接受。我测试过了,在perl 5.0.10中至少可以接受空字符串。 - derobert
1
抱歉,当然是Perl 5.10.0! - derobert

7

尝试使用这个正则表达式:

^(.{0,2}|([^A]..|A[^B].|AB[^C])|.{4,})$

这段文字描述了三种情况:

  1. 少于三个任意字符
  2. 正好三个字符,但是要满足以下条件之一:
    • 第一个字符不是 A
    • 第一个字符是 A 但第二个字符不是 B
    • 第一个字符是 A,第二个字符是 B 但第三个字符不是 C
  3. 多于三个任意字符

6
你可以使用负向先行断言或类似的方法,例如:
^([^A]|A([^B]|B([^C]|$)|$)|$).*$

也许可以简化一下。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接