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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 09:52:11  来源:igfitidea点击:

Regex to match against something that is not a specific substring

提问by John Meagher

I am looking for a regex that will match a string that starts with one substring and does not end with a certain substring.

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

Example:

例子:

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

Should match anything that starts with "foo" and doesn't end with "bar". I know about the [^...] syntax, but I can't find anything that will do that for a string instead of single characters.

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

I am specifically trying to do this for Java's regex, but I've run into this before so answers for other regex engines would be great too.

我特别想为 Java 的正则表达式做这件事,但我之前遇到过这个问题,所以其他正则表达式引擎的答案也会很棒。

Thanks to @Kibbee for verifying that this works in C# as well.

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

采纳答案by Apocalisp

I think in this case you want negative lookbehind, like so:

我认为在这种情况下,您需要负面的lookbehind,如下所示:

foo.*(?<!bar)

回答by Sam Hasler

I'm not familiar with Java regex but documentation for the Pattern Classwould suggest you could use (?!X) for a non-capturing zero-width negative lookahead (it looks for something that is not X at that postision, without capturing it as a backreference). So you could do:

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

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

Update: Apocalisp's right, you want negative lookbehind. (you're checking that what the .* matches doesn't end with bar)

更新:Apocalisp 是对的,你想要负面的回顾。(您正在检查 .* 匹配的内容不以 bar 结尾)

回答by aku

As other commenters said, you need a negative lookahead. In Java you can use this pattern:

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

"^first_string(?!.?second_string)\z"
  • ^ - ensures that string starts with first_string
  • \z - ensures that string ends with second_string
  • (?!.?second_string) - means that first_string can't be followed by second_string
  • ^ - 确保字符串以 first_string 开头
  • \z - 确保字符串以 second_string 结尾
  • (?!.?second_string) - 表示 first_string 后面不能跟 second_string

回答by John Meagher

Verified @Apocalisp's answer using:

使用以下方法验证@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());
  }
}

This output the the right answers:

这将输出正确的答案:

false
false
false
true
true
true