16

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

例子:

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

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

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

感谢@Kibbee 验证这也适用于 C#。

4

4 回答 4

9

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

foo.*(?<!bar)
于 2008-09-04T01:37:42.200 回答
1

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

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

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

于 2008-09-04T01:33:11.163 回答
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
于 2008-09-04T01:46:20.790 回答
0

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

"^first_string(?!.?second_string)\\z"
  • ^ - 确保字符串以 first_string 开头
  • \z - 确保字符串以 second_string 结尾
  • (?!.?second_string) - 表示 first_string 后面不能跟 second_string
于 2008-09-04T01:37:19.470 回答