Java中使用OR管道符号进行正则表达式匹配

4

我试图进行以下匹配,但结果并未如预期返回true:

String attrs = "id|fullname|email|title";
String regex = "fullname|email";
return attrs.matches(regex);

然而它返回了false。

为什么会这样呢?我本以为attrs中的|管道字符会被按照ASCII字符进行解释,而regex中的|管道字符会按照正则表达式进行解释(也就是OR)。

我问这个问题是因为我正在编写一个应用程序,其中我让用户使用attr1|attr2|attr3|...格式来设置属性,我想通过将其与可能的属性值进行匹配来验证他/她的输入:attr1|attr2|attr3|... |attr[n]。

感谢您的帮助,
ktm


通过以下方式使其正常工作:

String regex = "id.*|fullname.*|email.*|title.*";
String attrs = "fullname|email";
return attrs.matches(regex);
3个回答

7
问题在于管道符号是正则表达式中的元字符。因此,如果您想匹配一个字面上的 '|' 字符,就需要对其进行转义。
String attrs = "id|fullname|email|title";
String regex = "fullname\\|email";
return attrs.matches(regex);

另一个问题是你的用例真正需要使用find而不是matches,而String API不支持find。这意味着你需要重写它,以使用显式的PatternMatcher,例如:
String attrs = "id|fullname|email|title";
Pattern regex = Pattern.compile("fullname\\|email");
return regex.matcher(attrs).find();

但即使这样也不太对:

  1. 我认为你真正需要做的是,无论用户以什么顺序提供属性,都要匹配提供的属性。
  2. 上面的简单正则表达式如果用户输入类似“meaningfullname”的内容将无法匹配。

实际上,使用正则表达式来完成这个任务已经变得太复杂了。相反,你最好使用像下面这样的方法:

List<String> attrs = Arrays.asList(
        new String[] {"id", "fullname", "email", "title"});
String[] suppliedAttrs = supplied.split("\\|");
for (String s: suppliedAttrs) {
    if (!attrs.contains(s)) {
        throw new IllegalArgumentException("'" + s + "' is not valid");
    }
}

如果您只想测试属性是否包含一个或多个fullnameemail,可以使用以下方法:

String[] suppliedAttrs = supplied.split("\\|");
for (String s: suppliedAttrs) {
    if (s.equals("fullname") || s.equals("email")) {
        System.err.println("BINGO!");
    }
}

谢谢!实际上我不想匹配一个字面上的 '|' 字符。我只是将其作为分隔属性的语法手段。 - ktm5124
@ktm5124 - 我已经弄清楚了。请看我的更新答案。 - Stephen C

7

java String::matches()方法只匹配整个字符串。您需要使用类似以下内容的方法:

尝试:regex =".*(fullname|email).*;

或者使用Pattern类

更好的方法是String[] rattrs = attrs.split("\\|")然后检查每个字符串。


你为什么认为另一种方式更好?它需要更多的代码!(计算量更少吗?) - ktm5124
我建议您尝试运行所建议的代码并检查其结果。它没有做你想要的事情。 - tchrist
我有一组有限的属性(实际上这四个是完整的集合)。我相信唯一不起作用的情况是,如果有一个前导字符序列与属性不匹配。但在那种情况下,程序将不能正确配置,我也不希望它运行。此外:代码通过了我所有的测试。 - ktm5124
2
实际上,split("\|")甚至无法编译。要在正则表达式\|上拆分,您必须编写split("\\|") - Alan Moore
是的,我忘了。Java正则表达式总是因为“\”这个东西而让人头疼。 - KitsuneYMG
显示剩余2条评论

2

您正在使用matches而不是find,因此它必须与整个字符串相对应。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接