正则表达式接受带有额外 % 的字母和字母数字的最大值(无限制)

Regex accept max of alpha and alphanumeric with extra % (without limit)

我在正则表达式帖子中进行了大量搜索,但没有找到我正在寻找的解决方案。

我有正则表达式 ([a-zA-Z]{6}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3 })?)? 接受这些情况:

现在,我正在寻找的是修改我的正则表达式以在任何地方接受额外的可选字符 %,但保留数字 MAX 仅限当前正则表达式中的字母和字母数字。

示例:

可以吗?

下面的正则表达式应该足够接近了。

^(?:(?=.*%)(?![A-Z]{1,5}[0-9])(?:%?[A-Z]){0,6}(?:(?:%?[A-Z0-9]){1,2})?(?:(?:%?[A-Z]){1,3})?%?)$|^(?:[A-Z]{6}(?:[A-Z0-9]{2})(?:[A-Z]{3})?)$|^$

注意管道 (| = OR) 如何分隔 3 个正则表达式。
一个是有 % 的,然后是没有 % 的,然后是空白。

另外,字符类只使用大写A-Z
因此,为了也允许小写字母,要么让正则表达式忽略大小写,要么用 A-Za-z.

替换它们

你可以测试一下here

更短的选择:

^(?=.*%)(?![A-Z]{1,5}[0-9])(?!(?:.*?[0-9]){3})(?:%?[A-Z0-9]){1,11}%?$|^(?:[A-Z]{6}[A-Z0-9]{2}(?:[A-Z]{3})?)$|^$

这会让一些人感到惊讶。我正在为我的解决方案使用正则表达式,但与问题相反。

带有 % 符号的输入字符串是我的正则表达式。百分号是一个通配符(如您所说的 SQL)。所以我要将已知的正确字符串与带通配符的字符串进行匹配。正确的字符串包括空字符串 AAAAAA33AAAAAA33AAA.

停下来,你在想,这行不通有几个原因。首先,字母可以是英文字母表中的任何字母,而不仅仅是大写字母 A。而且数字不仅是 3。没错,所以我们必须替换它们。所以我要将您的输入字符串 AABB 更改为 AAAA,等等

input.replaceAll("[a-zA-Z]", "A")

我们还需要用同样的方法替换数字

replaceAll("[0-9]", "3")

我们需要注意中间的两个字母数字字符。如果它们在输入中是按字母顺序排列的,它们仍然不会匹配我上面给出的正确字符串中的 3。幸运的是它们只有两个,所以我们可以使用更正确的模型字符串来处理这个问题。为了涵盖问题中的所有三种情况,我使用了 9 个字符串:

static final String[] correctModels = {
    "", "AAAAAAAA", "AAAAAAA3", "AAAAAA3A", "AAAAAA33", 
    "AAAAAAAAAAA", "AAAAAAA3AAA", "AAAAAA3AAAA", "AAAAAA33AAA"
};

现在,如果在将字母替换为 A 并将数字替换为 3 之后,这些模型字符串之一与输入匹配,则输入正确。

接下来,Java 正则表达式无法将 % 识别为通配符。因此更改为 .*(包括空序列在内的任何序列的正则表达式模式):

replaceAll("%", ".*")

我们可能使用过 [a-zA-Z0-9]*,但由于我们可以完全控制模型字符串,因此我们不需要。

就是这样,我们准备好了。不用等,用户可以通过在输入字符串中放入有效的正则表达式语法来愚弄我们。解决方案:首先,检查输入是否仅包含字母、数字和百分号。这解决了它,因为其中 none 在正则表达式中有任何特殊含义。

public static boolean matches(String input) {
    // if input contains other chars than letter digits and percent, reject it
    if (! input.matches("[a-zA-Z0-9%]*")) {
        return false;
    }
    input = input.replaceAll("[a-zA-Z]", "A")
            .replaceAll("[0-9]", "3")
            .replaceAll("%", ".*");
    Pattern p = Pattern.compile(input);
    for (String model : correctModels) {
        if (p.matcher(model).matches()) {
            return true;
        }
    }
    return false;
}

我已经用问题中的所有示例进行了测试。它们按规定工作。我相信解决方案对于所有可能的输入都是正确的。