开发者

Java String.matches regex with OR pipe [duplicate]

This question already has answers here: Difference between matches() and find() in Java Regex (5 answers) Closed 4 years ago.

I am trying to make the following match, but it is not returning true as I would expect:

String attrs = "id|fullname|email|title";
String regex = "fullname|email";
return attrs.matches(regex);
开发者_运维技巧

Instead it returns false.

Why is this? I expect the | pipe in attrs to be interpreted literally as an ASCII character, and the | pipe in regex to be interpreted according to regular expressions (i.e. OR).

The reason I ask is because I am writing an application where I let the user set the attributes in the format attr1|attr2|attr3|..., and I want to verify his/her input by matching it against the possible attribute values: attr1|attr2|attr3|...|attr[n].

Help appreciated,

ktm


Got it working by doing

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


The problem is that the pipe character is a meta-character in regexes. It therefore needs to be escaped if you want to match a literal '|' character.

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

The other problem is that your usecase really needs to be using find rather than matches, and the String API does not support find. This means you need to rewrite it to use an explicit Pattern and Matcher; e.g.

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

But even this is not right:

  1. What you really need to do (I think) is match the supplied attributes independent of the order in which the user provides them.
  2. Naive regexes above will mismatch if the user enters something like "meaningfullname".

Really, this is getting too complicated to do using regexes. Instead, you are better off with something like this:

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");
    }
}

or if you just want to test if the attributes contain one or more of fullname and email

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


java String::matches() matches only whole strings. You need something like

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

Or use the Pattern class

A better way of doing what you want is String[] rattrs = attrs.split("\\|") and then check each string.


You're using matches, not find, so it must correspond with the whole string.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜