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

16
我正在寻找一个正则表达式,它可以匹配以某个子字符串开头但不以特定子字符串结尾的字符串。
例子:
// Updated to be correct, thanks @Apocalisp
^foo.*(?<!bar)$

正则表达式应该匹配任何以“foo”开头且不以“bar”结尾的内容。我知道有关于 [^...] 语法,但我找不到与字符串相关的可用语法。

我特别是想在 Java 的正则表达式中实现这个,但我以前也遇到过这个问题,因此适用于其他正则表达式引擎的答案也很好。感谢 @Kibbee 验证了这在 C# 中也适用。


正如我在下面提到的那样 - 对于输入字符串 "foo123bar" 的正则表达式将匹配 "foo12" - 希望这是期望的行为。 - Dmitry
4个回答

9
我认为在这种情况下,您需要使用负回顾后断言,如下所示:
foo.*(?<!bar)

1

使用 @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

1

我不熟悉Java正则表达式,但Pattern Class的文档建议您可以使用(?!X)来进行非捕获零宽度负向先行断言(它在该位置查找不是X的内容,而不将其作为后向引用捕获)。因此,您可以这样做:

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

更新:Apocalisp是对的,你需要负向前视断言。(你要检查.*匹配的内容不能以bar结尾)


这个解决方案的问题在于对于输入字符串“foo123bar”,它将匹配“foo12” - 希望这是期望的行为。 - Dmitry

0

正如其他评论者所说,您需要一个负向先行断言。在Java中,您可以使用以下模式:

"^first_string(?!.?second_string)\\z"
  • ^ - 确保字符串以 first_string 开始
  • \z - 确保字符串以 second_string 结尾
  • (?!.?second_string) - 意味着 first_string 不能跟在 second_string 后面

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