【问题标题】:Combining or and negation in Java regex? [closed]在Java正则表达式中结合或和否定? [关闭]
【发布时间】:2019-12-23 02:30:44
【问题描述】:

我正在尝试结合使用“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...... 的字符串,其中字符不是 as、bs、或cs。我只是选择“blah”作为一般示例,例如“foo”或“bar”。

【问题讨论】:

  • 这不是负前瞻,因为那是在避免未来的元素。我只想检查当前元素是否匹配。
  • @Turing85 它是否定的,但是在[]的字符集上下文中
  • 仅供参考: [^h|bla] 表示“不是 h|bl 或 @987654334 @",但^只在首位有特殊含义,所以[bla|^h]表示“一个b,l,a,|,^,或者h”。跨度>
  • @Andreas 哦,这听起来有问题。以后我会记住这一点的:)
  • 总体评论:您当前的正则表达式语义说:如果一个字符既不是'b''l''a',那么它一定不是'h'。换句话说:一个字符可以是任何东西,除了h。这真的是你想要的吗?

标签: java regex string-matching regex-negation


【解决方案1】:

“not h”可以有多种写法:

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

"b,l,a 中的任何一个"1:

[bla]*

1) 假设您的意思是“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

【讨论】:

    【解决方案2】:

    要结合您的条件,请在非捕获组中使用单独的替代字符集 [],所以

    "[bla|^h]*" 会是

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

    类似于“至少出现一次 (b,l,a or not h)”

    请记住,与* 匹配意味着“可能发生”(技术上为零或更多)

    【讨论】:

    • [^h] 允许 b's、l's 和 a's 以及除 h's 以外的任何其他内容,因此 [bla]|[^h] 非常多余,当然不是您想要的
    • @Andreas 你想让我纠正 OP 的要求吗?
    • @Antoniossss 您的正则表达式无法编译。是什么 ?一开始一个人做?
    • 它不见了 (?:
    • @Antoniossss 啊,非捕获? -1 移除
    【解决方案3】:

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

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

    接下来你可以使用 2 个:

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

    正则表达式详细信息:

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

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

    【讨论】:

    • [^h] 允许 b's、l's 和 a's 以及除 h's 之外的任何其他内容,因此 [bla]|[^h] 非常多余,当然不是你想要的
    • 你说得对,OP的要求本身就是模糊的。
    • @Avi:您需要澄清要求,因为 not h 满足 [bla,因此不需要任何 OR 条件。
    • 根据我的要求,这应该是正确的。非捕获组可能不是必需的,但没关系。
    • 很高兴知道,但请记住,^[^h]*$ 也适用于您。
    猜你喜欢
    • 2015-04-27
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多