首页 > 解决方案 > Java 正则表达式验证器

问题描述

我将从 REST 服务请求有效负载中获取 where 子句字符串(仅用 AND/OR 运算符分隔的条件)。我想使用正则表达式验证输入字符串。条件将包含键运算符值格式的每个个体。

我在某种程度上尝试了实现这一目标。我是正则表达式的新手。我写了一些代码来验证这一点。但它正在部分工作。有人可以建议正确的正则表达式,如果可能的话,请解释它是如何工作的。这很有帮助。

所以我的问题是:我的正则表达式是否正确?如果是,为什么 matches() 方法对第二个和第三个输入字符串返回 false

为了使它在任何复杂字符串出现时变得健壮,这个正则表达式会处理吗?例如:“(userName eq \"bjensen\" and familyName co \"O'Malley\") OR (userName eq \"bjensen\" or familyName co \"O'Malley\")"

我正在粘贴我的代码片段。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DummyTester {
    public DummyTester() {
        super();
    }

    public static void main(String[] args) {

        checkRegex("userName eq \"bjensen\"");  // returning Matches True
        checkRegex("(userName eq \"bjensen\" and familyName co \"O'Malley\")"); // returning matches False
        checkRegex("(userName eq \"bjensen\" and familyName co \"O'Malley\" AND userName eq \"bjensen\" AND familyName co \"O'Malley\")"); // returning matches False

    }

    static String checkRegex(String tester) {

        String regex ="(\\w[\\w\\d]* \\s*(?:co|eq|gt)\\s* \\\"\\w[\\w\\d\\-\\:\\']*\\\")* ?(?:and|or|AND|OR)?";
        System.out.println("The input rgex  sis : "+regex);
        System.out.println("The input String sis : "+tester);
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(tester);
        boolean b = m.matches(); 
        System.out.println("matcher is   : "+ b);
        while (m.find()) {
            System.out.println(m.group());
        }
        return null;
    }

}

上述代码片段的输出如下。

输出:

输入 rgex sis : (\w[\w\d]* \s*(?:co|eq|gt)\s* \"\w[\w\d-:\'] \") ?(? :and|or|AND|OR)?

输入字符串 sis : userName eq "bjensen"

匹配器是:真

输入字符串 sis : (userName eq "bjensen" and familyName co "O'Malley")

匹配器是:假

用户名 eq "bjensen" 和

familyName co“奥马利”

输入字符串 sis : (userName eq "bjensen" and familyName co "O'Malley" AND userName eq "bjensen" AND familyName co "O'Malley")

匹配器是:假

用户名 eq "bjensen" 和

familyName co“O'Malley”和

用户名 eq “bjensen” AND

familyName co“奥马利”

谢谢,维杰

标签: javaregex

解决方案


matches()函数尝试将整个输入正则表达式与您的输入进行匹配。您的正则表达式正在寻找:

[name] [operator] [string] [optional and-or]

因此,当您输入多个条件时,例如:"(userName eq \"bjensen\" and familyName co \"O'Malley\")",正则表达式将不会匹配整个输入,而只会匹配第一个and。但第一个测试字符串不是这种情况,即"userName eq \"bjensen\"".

所以你的代码需要是:

    boolean b = m.matches();
    System.out.println("matcher is   : "+ b);
    if (b) { // we have a complete match
        System.out.println(m.group());
    }
    else {
        while (m.find()) {
            System.out.println(m.group());
        }
    }

但是有一些事情可以用你的正则表达式来改进。首先,您定义它的方式,它将接受为有效输入:

用户名 eq "bjensen" 和

...它有一个“悬空”和

如果您假设输入始终正确并且您不需要验证输入,这可能不是问题。但我建议对不允许上述字符串的正则表达式进行更改。此外,字符类\w实际上等价于[A-Za-z0-9_]. 您正在尝试将名称匹配到:

\w[\w\d]*

\w已经包括了所有的数字。我猜你真正想说的是第一个字符必须是字母字符,后续字符可以是字母数字。表达方式是:

[a-z][a-z0-9]*

为什么我没有包括范围A-Z?因为我会为正则表达式设置不区分大小写的标志(?i)。这也意味着我可以通过不必同时测试or和来简化不同运算符的测试OR

您还使用不需要转义的反斜杠转义了许多字符,例如分号。

最终的正则表达式是:

(?i)               # Turn on case-insensitive flag
[a-z][a-z0-9]*     # Match alpha followed by 0 or more alphanumeric characters
\s+                # Match one or more white space characters
(?:co|eq|gt)       # Match "co" or "eq" or "gt"
\s*                # Match 0 or more white space characters
"                  # Match a double quote
[^"]*              # Match 0 or more non-double quote characters
"                  # Match a double quote
(?:                # Start of a non-capturing group
    \s+            # Match one or more white space characters
    (?:and|or)     # Match "and" or "or"
    \s+            # Match one or more white space characters
    [a-z][a-z0-9]* # Match a name as before
    \s+            # Match 1 or more white space characters
    (?:co|eq|gt)   # Match an operator as before
    \s*            # Match 0 or more white space characters
    "[^"]*"        # Match a string as before
)*                 # Optional non-capturing group repeated 0 or more times

正则表达式演示

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DummyTester {
    public DummyTester() {
        super();
    }

    public static void main(String[] args) {

        checkRegex("userName eq \"bjensen\"");  // returning Matches True
        checkRegex("(userName eq \"bjensen\" and familyName co \"O'Malley\")"); // returning matches False
        checkRegex("(userName eq \"bjensen\" and familyName co \"O'Malley\" AND userName eq \"bjensen\" AND familyName co \"O'Malley\")"); // returning matches False

    }

    static String checkRegex(String tester) {

        String regex ="(?i)[a-z][a-z0-9]*\\s+(?:co|eq|gt)\\s*\"[^\"]*\"(?:\\s+(?:and|or)\\s+[a-z][a-z0-9]*\\s+(?:co|eq|gt)\\s*\"[^\"]*\")*";
        System.out.println("The input regex  sis : "+regex);
        System.out.println("The input String sis : "+tester);
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(tester);
        boolean b = m.find();
        System.out.println("finder is   : "+ b);
        if (b) {
            String s = m.group();
            System.out.println(s);
            return s;
        }
        return null;
    }

}

印刷:

The input regex  sis : (?i)[a-z][a-z0-9]*\s+(?:co|eq|gt)\s*"[^"]*"(?:\s+(?:and|or)\s+[a-z][a-z0-9]*\s+(?:co|eq|gt)\s*"[^"]*"*)
The input String sis : userName eq "bjensen"
finder is   : true
userName eq "bjensen"
The input regex  sis : (?i)([a-z][a-z0-9]*\s+(?:co|eq|gt)\s*"[^"]*"(?:\s+(?:and|or)\s+[a-z][a-z0-9]*\s+(?:co|eq|gt)\s*"[^"]*")*)
The input String sis : (userName eq "bjensen" and familyName co "O'Malley")
finder is   : true
userName eq "bjensen" and familyName co "O'Malley"
The input regex  sis : (?i)([a-z][a-z0-9]*\s+(?:co|eq|gt)\s*"[^"]*"(?:\s+(?:and|or)\s+[a-z][a-z0-9]*\s+(?:co|eq|gt)\s*"[^"]*")*)
The input String sis : (userName eq "bjensen" and familyName co "O'Malley" AND userName eq "bjensen" AND familyName co "O'Malley")
finder is   : true
userName eq "bjensen" and familyName co "O'Malley" AND userName eq "bjensen" AND familyName co "O'Malley"

Java 演示


推荐阅读