【问题标题】:Combine whitelist and blacklist in java regex expression在java正则表达式中结合白名单和黑名单
【发布时间】:2016-04-14 09:32:35
【问题描述】:

我在构建允许所有 UTF-8 字符范围的正则表达式时遇到问题,但 2 个字符除外:'_' 和 '?'

所以白名单是:^[\u0000-\uFFFF] 黑名单是:^[^_%]

我需要将这些组合成一个表达式。

我尝试了以下代码,但没有按照我希望的方式工作:

    String input = "this";
    Pattern p = Pattern
            .compile("^[\u0000-\uFFFF]+$ | ^[^_%]");
    Matcher m = p.matcher(input);
    boolean result = m.matches();
    System.out.println(result);

输入:这个
实际输出:假
期望的输出:真

【问题讨论】:

  • 更新代码,有效输入返回false
  • 您应该提供输入和所需输出的示例。
  • 从这个文档:docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html,你可以试试这个:[a-z&&[^m-p]] a 到 z,而不是 m 到 p:[a-lq-z](减法) .一个完整的字符范围,除了其他范围。
  • 你可以试试这个-Pattern p = Pattern.compile("(?!.*[_%])[\u0000-\uFFFF]+");
  • 感谢 Jose Luis,我需要嵌套表达式。

标签: java regex


【解决方案1】:

您可以在 Java 正则表达式中使用 character class intersections/subtractions 来限制“通用”字符类。

字符类[a-z&&[^aeiuo]] 匹配一个非元音字母。换句话说:它匹配一个辅音。

使用

"^[\u0000-\uFFFF&&[^_%]]+$"

匹配除_% 之外的所有Unicode 字符。

有关 Java 正则表达式中可用的字符类交集/减法的更多信息,请参阅The Java™ Tutorials: Character Classes

OCPSoft Visual Regex Tester 的测试显示当% 添加到字符串时不匹配:

还有Java demo

String input = "this";
Pattern p = Pattern.compile("[\u0000-\uFFFF&&[^_%]]+"); // No anchors because `matches()` is used
Matcher m = p.matcher(input);
boolean result = m.matches();
System.out.println(result); // => true

【讨论】:

  • 加上 1 个使用交叉点的好解决方案。
【解决方案2】:

这是一个示例代码,用于从使用 Lookahead and Lookbehind Zero-Length Assertions 的范围中排除一些字符,这些字符实际上不消耗字符串中的字符,而只是断言是否可能匹配。

示例代码:(从a-z 范围内排除mn

    String str = "abcdmnxyz";
    Pattern p=Pattern.compile("(?![mn])[a-z]");
    Matcher m=p.matcher(str);
    while(m.find()){
        System.out.println(m.group());
    }

输出:

a b c d x y z

以同样的方式你可以做到。

正则表达式解释(?![mn])[a-z]

  (?!                      look ahead to see if there is not:   
    [mn]                     any character of: 'm', 'n' 
  )                        end of look-ahead    
  [a-z]                    any character of: 'a' to 'z'

您可以将整个范围划分为子范围,也可以使用([a-l]|[o-z])[a-lo-z] 正则表达式解决上述问题。

【讨论】:

  • 有更好的方法使用字符集交集。
  • 请您将其添加为答案,以便我也可以学习它。也可以有其他方式,例如([a-l]|[o-z])
  • 您的解决方案非常适合在 JavaScript 和 Python re 中使用。如果解决方案必须在 Java、Python 和 JS 之间移植,这是一个很好的方法。
【解决方案3】:

你的问题是管道两边的空格。

两者都不是

" ^.*"
".*$ "

将匹配任何内容,因为在 start 之前或 end 之后什么都不会出现。

这有机会:

^[\u0000-\uFFFF]+$|^[^_%]

【讨论】:

    猜你喜欢
    • 2021-05-06
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    相关资源
    最近更新 更多