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

xpcnnkqh  于 2023-11-15  发布在  Java
关注(0)|答案(2)|浏览(116)

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

"(?<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位数的字符串作为第一部分,如果后面出现的东西,它应该看起来像-{numbers/letters}_{numbers}_{numbers}谢谢。Edit1:
不匹配:

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

jchrr9hc

jchrr9hc1#

  • "..

.什么是奇怪的12321324143432142352546534636534343243525425是匹配的。
从技术上讲,模式应该包括 * 单词边界 *,或一些 * 静态值 * 来锚。

  • "...如何让我的正则表达式模式验证14位数的字符串作为第一部分,如果之后出现的东西,它应该看起来像-{numbers/letters}_{numbers}_{numbers} ..."*

这里有一个例子,省略了 * 组名 *。我在本文的结尾包含了完整的模式。

\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+))?)?))?(?: |$)

ev7lccsx

ev7lccsx2#

您的示例在第一部分后面有一个下划线_,但您的正则表达式有一个连字符-,因此我通过假设您的示例是正确的来更正该错误。
正则表达式的主要问题是:
1.你让可选部分的所有子部分都是可选的--它们不应该是可选的。* 整个 * 可选部分应该存在或不存在。
1.分隔符(下划线/连字符)必须是可选组的一部分。2你的编码方式使得它在第一部分之后是必需的,不管最后的可选组是否存在。
试试这个:

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

字符串
请参阅live demo
为了便于阅读,我删除了所有组名。
我还添加了^$,因为我不知道你是如何使用它的。如果你正在使用String#matches(),你可以删除它们。

相关问题