Java String.matches正则表达式与OR管道

ktm*_*124 2 java regex

我正在尝试进行以下匹配,但它没有像我期望的那样返回true:

String attrs = "id|fullname|email|title";
String regex = "fullname|email";
return attrs.matches(regex);
Run Code Online (Sandbox Code Playgroud)

相反,它返回false.

为什么是这样?我期待| attrs中的管道按字面解释为ASCII字符,以及| 正则表达式中的管道根据正则表达式(即OR)进行解释.

我问的原因是因为我正在编写一个应用程序,我让用户以attr1 | attr2 | attr3 | ...的格式设置属性,我想通过将它与可能的属性值进行匹配来验证他/她的输入: attR1位| attR2位| attr3 | ... | ATTR [N].

帮助赞赏,
ktm


通过这样做工作

String regex = "id.*|fullname.*|email.*|title.*";
String attrs = "fullname|email";
return attrs.matches(regex);
Run Code Online (Sandbox Code Playgroud)

Ste*_*n C 7

问题是管道字符是正则表达式中的元字符.因此,如果要匹配文字'|'字符,则需要进行转义.

String attrs = "id|fullname|email|title";
String regex = "fullname\\|email";
return attrs.matches(regex);
Run Code Online (Sandbox Code Playgroud)

另一个问题是你的用例确实需要使用find而不是matches,并且StringAPI不支持find.这意味着你需要重写它以使用显式PatternMatcher; 例如

String attrs = "id|fullname|email|title";
Pattern regex = Pattern.compile("fullname\\|email");
return regex.matcher(attrs).find();
Run Code Online (Sandbox Code Playgroud)

但即使这样也不对:

  1. 你真正需要做的(我认为)与提供的属性相匹配,与用户提供它们的顺序无关.
  2. 如果用户输入类似"有用名称"的内容,则上面的朴素正则表达式将不匹配.

真的,使用正则表达式变得太复杂了.相反,你最好用这样的东西:

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");
    }
}
Run Code Online (Sandbox Code Playgroud)

或者如果你只是想测试是否属性包含一个或多个fullnameemail

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


Kit*_*YMG 5

java String :: matches()仅匹配整个字符串.你需要类似的东西

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

或者使用Pattern类

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

  • 实际上,`split("\ |")`甚至不会编译.要拆分*regex*`\ |`,你必须写`split("\\ |")`. (2认同)