Java 正则表达式模式数学无效可选部分

Java regex pattern mathes not valid optional part

提问人:Ivan Karotki 提问时间:11/14/2023 最后编辑:Ivan Karotki 更新时间:11/14/2023 访问量:87

问:

我在代码中有以下正则表达式模式:

"(?<part1>(?<year>\\d{4})(?<day>\\d{3})(?<number>[A-Z0-9]{3})(?<sequence>\\d{4}))-(?<lastPart>(?<letter>[A-Z0-9]+)_?(?<num1>\\d+)?_?(?<num2>\\d+)?)"

我已将其更改为以下内容,使其成为可选的:<lastPart>

"(?<part1>(?<year>\d{4})(?<day>\d{3})(?<number>[A-Z0-9]{3})(?<sequence>\d{4}))-?(?<lastPart>(?<letter>[A-Z0-9]+)_?(?<num1>\d+)?_?(?<num2>\d+)?)?"

我正在更新它,因为 14 位字符串也是有效的,但是运行测试我发现无效字符串

20221239990001_AB
20221239990001_ABC#$%
20221239990001_+AB><
20221239990001_-*AB___
20221239990001_AB12232434

也是有效的,这是错误的。 如何让我的正则表达式模式验证 14 位字符串作为第一部分,如果之后出现的内容,它应该看起来像谢谢。 编辑1:-{numbers/letters}_{numbers}_{numbers}

不匹配:

2022123999000
202212399900
2022123999

但奇怪的是匹配。12321324143432142352546534636534343243525425

编辑2: 可选部件包含可选子部件 所以:

12233255555555 valid
12233255555555- invalid
12233255555555-A valid
12233255555555-A_ invalid
12233255555555-A_1 valid
12233255555555-A_1_ invalid
12233255555555-A_1_1 valid
12233255555555-A__1 invalid
12233255555555-A__ invalid
Java 正则表达式

评论

2赞 Tim Biegeleisen 11/14/2023
应包括匹配和不匹配的示例数据。
0赞 Vasanth Subramanian 11/14/2023
你能试试这个,让我知道这是否适用于你提到的所有测试用例吗^\d{14}(?:-[a-zA-Z0-9]+_\d+_\d+)?$
0赞 Bohemian 11/14/2023
对于初学者来说,你的模式有你的示例,你的“数字”组允许字母(?),但你的例子那里没有字母。另外,请删除所有组名 - 没有它们就很难阅读正则表达式。-_

答:

1赞 Bohemian 11/14/2023 #1

您的示例在第一部分之后有一个下划线,但您的正则表达式有一个连字符,因此我通过假设您的示例是正确的来纠正该错误。_-

正则表达式的主要问题是:

  1. 您已将可选部件的所有子部件设置为可选 - 它们不应是可选的。整个可选部分应该存在或不存在。
  2. 分隔符(下划线/连字符)必须是可选组的一部分。根据对它的编码方式,无论最终的可选组是否存在,它都是在第一部分之后必填的。

试试这个:

^(\d{4})(\d{3})([A-Z0-9]{3})(\d{4})(_([A-Z0-9]+)_(\d+)_(\d+))?$

观看现场演示

为了便于阅读,我删除了所有组名称。

我还添加了,因为我不知道你如何使用它。如果您使用的是 ,则可以删除这些内容。^$String#matches()

评论

0赞 Ivan Karotki 11/14/2023
您好,最终得到了类似以下内容的内容,它工作正常,除了一种情况:超过 14 位数字的字符串 (1232132414323134242342423) 仍然有效。regex101.com/r/BJItcS/1^(\d{4})(\d{3})([A-Z0-9]{3})(\d{4})(-?([A-Z0-9]+)(_?(\d+))?(_?(\d+))?)?$
1赞 Reilas 11/14/2023 #2

"...我已将其更改为以下,使<lastPart>可选...

。奇怪的是12321324143432142352546534636534343243525425匹配。

从技术上讲,该模式应包括单词边界或一些要锚定的静态值

"...如何让我的正则表达式模式验证 14 位字符串作为第一部分,如果后面出现的内容,它应该看起来像 -{数字/字母}_{数字}_{数字} ......”

下面是一个示例,省略了组名称。我在本文末尾包含了完整的模式。

\b(\d{4})(\d{3})([A-Z\d]{3})(\d{4})(?:-([A-Z\d]+)(?:_(\d+)(?:_(\d+))?)?)?(?: |$)

下面是一个示例应用程序。

String r = "\\b(?<part1>(?<year>\\d{4})(?<day>\\d{3})(?<number>[A-Z\\d]{3})(?<sequence>\\d{4}))(?:-(?<lastPart>(?<letter>[A-Z\\d]+)(?:_(?<num1>\\d+)(?:_(?<num2>\\d+))?)?))?(?: |$)";
String s = "12233255555555 valid\n"
         + "12233255555555- invalid\n"
         + "12233255555555-A valid\n"
         + "12233255555555-A_ invalid\n"
         + "12233255555555-A_1 valid\n"
         + "12233255555555-A_1_ invalid\n"
         + "12233255555555-A_1_1 valid\n"
         + "12233255555555-A__1 invalid\n"
         + "12233255555555-A__ invalid";
Pattern p = Pattern.compile(r);
Matcher m = p.matcher(s);
int i = 0;
while (m.find()) {
    System.out.println("match " + ++i);
    for (String k : m.namedGroups().keySet())
        System.out.printf("  %s = '%s'%n", k, m.group(k));
    System.out.println();
}

输出

match 1
  year = '1223'
  lastPart = 'null'
  number = '555'
  letter = 'null'
  day = '325'
  num1 = 'null'
  part1 = '12233255555555'
  sequence = '5555'
  num2 = 'null'

match 2
  year = '1223'
  lastPart = 'A'
  number = '555'
  letter = 'A'
  day = '325'
  num1 = 'null'
  part1 = '12233255555555'
  sequence = '5555'
  num2 = 'null'

match 3
  year = '1223'
  lastPart = 'A_1'
  number = '555'
  letter = 'A'
  day = '325'
  num1 = '1'
  part1 = '12233255555555'
  sequence = '5555'
  num2 = 'null'

match 4
  year = '1223'
  lastPart = 'A_1_1'
  number = '555'
  letter = 'A'
  day = '325'
  num1 = '1'
  part1 = '12233255555555'
  sequence = '5555'
  num2 = '1'

这是完整的模式。

\b(?<part1>(?<year>\d{4})(?<day>\d{3})(?<number>[A-Z\d]{3})(?<sequence>\d{4}))(?:-(?<lastPart>(?<letter>[A-Z\d]+)(?:_(?<num1>\d+)(?:_(?<num2>\d+))?)?))?(?: |$)