正则表达式匹配不是特定子字符串的内容

Posted

技术标签:

【中文标题】正则表达式匹配不是特定子字符串的内容【英文标题】:Regex to match against something that is not a specific substring 【发布时间】:2010-09-07 18:20:57 【问题描述】:

我正在寻找一个正则表达式,它将匹配以一个子字符串开头且不以某个子字符串结尾的字符串。

例子:

// Updated to be correct, thanks @Apocalisp
^foo.*(?<!bar)$

应匹配以“foo”开头且不以“bar”结尾的任何内容。我知道 [^...] 语法,但我找不到任何可以为字符串而不是单个字符执行此操作的内容。

我专门尝试为 Java 的正则表达式执行此操作,但我之前遇到过此问题,因此其他正则表达式引擎的答案也会很棒。

感谢@Kibbee 验证这在 C# 中也有效。

【问题讨论】:

正如我在下面提到的 - 输入字符串“foo123bar”的正则表达式将匹配“foo12” - 希望这是理想的行为。 【参考方案1】:

我不熟悉 Java 正则表达式,但 Pattern Class 的文档建议您可以使用 (?!X) 进行非捕获零宽度负前瞻(它在该位置寻找不是 X 的东西,而不将其捕获为反向引用)。所以你可以这样做:

foo.*(?!bar) // not correct

更新:Apocalisp 是对的,你想要消极的后视。 (您正在检查 .* 匹配的内容是否以 bar 结尾)

【讨论】:

此解决方案的问题在于,对于输入字符串“foo123bar”,它将匹配“foo12” - 希望这是所需的行为。【参考方案2】:

使用以下方法验证了@Apocalisp 的答案:

import java.util.regex.Pattern;
public class Test 
  public static void main(String[] args) 
    Pattern p = Pattern.compile("^foo.*(?<!bar)$");
    System.out.println(p.matcher("foobar").matches());
    System.out.println(p.matcher("fooBLAHbar").matches());
    System.out.println(p.matcher("1foo").matches());
    System.out.println(p.matcher("fooBLAH-ar").matches());
    System.out.println(p.matcher("foo").matches());
    System.out.println(p.matcher("foobaz").matches());
  

这会输出正确的答案:

false
false
false
true
true
true

【讨论】:

【参考方案3】:

我认为在这种情况下你想要消极的后视,就像这样:

foo.*(?<!bar)

【讨论】:

【参考方案4】:

正如其他评论者所说,您需要消极的前瞻性。在 Java 中,您可以使用这种模式:

"^first_string(?!.?second_string)\\z"
^ - 确保字符串以 first_string \z - 确保字符串以 second_string 结尾 (?!.?second_string) - 表示first_string后面不能跟second_string

【讨论】:

以上是关于正则表达式匹配不是特定子字符串的内容的主要内容,如果未能解决你的问题,请参考以下文章

js正则表达式 匹配两个特定字符间的内容

正则表达式,匹配特定字符后面的内容

正则表达式---重复

用正则表达批量快速解决如“过滤注释的//”“查询特定单词”“匹配特定子字符串”等工作中难题

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

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