在 Java 正则表达式中结合或和否定?

Combining or and negation in Java regex?

我正在尝试结合使用 "not" 和 "or" 来生成一组正则表达式匹配,如下所示:

"blah" matching "zero or more of" : "not h"         or  "any in b,l,a" = false 
"blah" matching "zero or more of" : "any in b,l,a"  or  "not h"        = false  
"blah" matching "zero or more of" : "not n"         or  "any in b,l,a" = true  
"blah" matching "zero or more of" : "any in b,l,a"  or  "not n"        = true  

我尝试了以下正则表达式,但它们似乎没有达到我的要求。我还包括了我对正则表达式的解释:

//first set attempt - turns out to be any of the characters within?
System.out.println("blah".matches("[bla|^h]*"));    //true
System.out.println("blah".matches("[^h|bla]*"));    //false
System.out.println("blah".matches("[bla|^n]*"));    //false
System.out.println("blah".matches("[^n|bla]*"));    //false
//second set attempt - turns out to be the literal text
System.out.println("blah".matches("(bla|^h)*"));    //false
System.out.println("blah".matches("(^h|bla)*"));    //false
System.out.println("blah".matches("(bla|^n)*"));    //false
System.out.println("blah".matches("(^n|bla)*"));    //false
//third set attempt - almost gives the right results, but it's still off somehow
System.out.println("blah".matches("[bla]|[^h]*"));  //false
System.out.println("blah".matches("[^h]|[bla]*"));  //false
System.out.println("blah".matches("[bla]|[^n]*"));  //true
System.out.println("blah".matches("[^n]|[bla]*"));  //false

所以,最后,我想知道以下问题:

  1. 我对上述正则表达式的解释是否正确?
  2. 什么是符合我的规范的四个 Java 正则表达式?
  3. (可选)我是否在我的正则表达式中犯了其他错误?

关于模糊的需求,我只想说明以下几点:
正则表达式细分可能类似于 ("not [abc]" 或 "bc")*,它会匹配任何类似于 bcbc...... 的字符串,其中字符不是 a秒、b 秒或 c 秒。我只是选择 "blah" 作为一般示例,例如 "foo" 或 "bar".

对于前 2 个条件,您可以使用:

^(?:[bla]|[^h])*$

接下来的 2 个你可以使用:

^(?:[bla]|[^n])*$

正则表达式详细信息:

  • ^: 开始
  • (?:: 启动非捕获组
    • [bla]:匹配b or l or a之一:
    • |: 或
    • [^h]:匹配任何非h
    • 的字符
  • )*:结束非捕获组,匹配0个或多个本组
  • $:结束 RegEx Demo

请注意,对于 .matches,锚点是隐式的,因此您可以省略 ^$

要结合您的标准,请在非捕获组中使用单独的替代字符集 [],因此

"[bla|^h]*" 将是

(?:[bla]*|[^h]*)+

类似于"at least one occurence of (b,l,a or not h)"

请记住,与 * 匹配意味着 "may occure"(技术上为零或更多)

"not h"可以有多种写法:

(?!.*h.*)
[^h]*

"any in b,l,a"1:

[bla]*

1) 假设您的意思是 "only one of b,l,a",否则问题中的所有 4 个示例都是 true

使用 or 的组合将是:

[^h]*|[bla]*

表示“必须是不包含h的字符串,或者必须是仅包含bla个字符的字符串。

在这种情况下,| 的顺序没有区别,因此 [^h]*|[bla]*[bla]*|[^h]* 的效果相同。

System.out.println("blah".matches("[bla]*|[^h]*"));  //false
System.out.println("blah".matches("[^h]*|[bla]*"));  //false
System.out.println("blah".matches("[bla]*|[^n]*"));  //true
System.out.println("blah".matches("[^n]*|[bla]*"));  //true