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

时间:2020-03-05 18:47:25  来源:igfitidea点击:

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

例子:

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

应该匹配以" foo"开头但不以" bar"结尾的任何内容。我知道[^ ...]语法,但是我找不到能对字符串(而不是单个字符)执行此操作的任何东西。

我专门尝试为Java的正则表达式执行此操作,但是我之前曾遇到过此问题,因此其他正则表达式引擎的答案也将非常有用。

感谢@Kibbee验证它在Cas中是否可以正常工作。

解决方案

回答

我不熟悉Java正则表达式,但是Pattern类的文档建议我们可以使用(?!X)进行非捕获的零宽度负前瞻(它在该姿势下查找不是X的东西,而不捕获它)作为反向参考)。因此,我们可以执行以下操作:

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

更新:Apocalisp的权利,我们想向后看。 (我们正在检查。*匹配的内容是否以bar结尾)

回答

正如其他评论者所说,我们需要提前否定。在Java中,我们可以使用以下模式:

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

回答

我认为在这种情况下,我们想在后面进行否定检查,例如:

foo.*(?<!bar)

回答

通过以下方式验证@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