Java String.matches regex 与 OR 管道

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4771447/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 07:57:08  来源:igfitidea点击:

Java String.matches regex with OR pipe

javaregex

提问by ktm5124

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

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

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

Instead it returns false.

相反,它返回 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).

为什么是这样?我期待 | attrs 中的管道从字面上解释为 ASCII 字符,而 | 正则表达式中的管道将根据正则表达式(即 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].

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

Help appreciated,
ktm

感谢帮助,
ktm



Got it working by doing

通过做得到它

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

回答by Stephen C

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 findrather than matches, and the StringAPI does not support find. This means you need to rewrite it to use an explicit Patternand Matcher; e.g.

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

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".
  1. 您真正需要做的(我认为)是匹配提供的属性,而与用户提供它们的顺序无关。
  2. 如果用户输入诸如“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 fullnameand email

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

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

回答by KitsuneYMG

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

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

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

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

Or use the Pattern class

或者使用 Pattern 类

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

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

回答by maaartinus

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

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