【问题标题】:Java support for conditional lookaheadJava 对条件前瞻的支持
【发布时间】:2012-02-15 06:05:38
【问题描述】:

在下面假设我试图从结果中排除 33333- 的邮政编码。
我愿意:

String zip = "11111 22222 33333- 44444-4444";
String regex = "\\d{5}(?(?=-)-\\d{4})";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(zip);
while (matcher.find()) { 
   System.out.println(" Found: " + matcher.group());     
}

期望得到:

Found:  11111  
Found:  22222  
Found:  44444-4444

我正在尝试强制执行以下格式:
5 位数字可选地后跟一个 - 和 4 位数字。不希望只有一个 -(连字符)的 5 位数字

我得到异常:

Exception in thread "main" java.util.regex.PatternSyntaxException: Unknown inline modifier near index 7
\d{5}(?(?=-)(-\d{4}))
       ^
    at java.util.regex.Pattern.error(Unknown Source)
    at java.util.regex.Pattern.group0(Unknown Source)
    at java.util.regex.Pattern.sequence(Unknown Source)
    at java.util.regex.Pattern.expr(Unknown Source)
    at java.util.regex.Pattern.compile(Unknown Source)
    at java.util.regex.Pattern.<init>(Unknown Source)
    at java.util.regex.Pattern.compile(Unknown Source)

我没有正确使用条件前瞻吗?

【问题讨论】:

  • 您希望最后一个匹配为44444-4444 还是只匹配44444
  • 我想得到11111 22222 44444-4444 但不是33333-。我认为不包括33333- 的条件展望

标签: java regex regex-lookarounds


【解决方案1】:

要捕获除 33333 之外的所有数字,请使用以下代码:

String zip = "11111 22222 33333- 44444-4444";
String regex = "\\d{5}(?=(-\\d{4}|\\s|$))(-\\d{4})?";
Matcher m = Pattern.compile(regex).matcher(zip);
while(m.find())
    System.out.printf("Macthed: [%s]%n", m.group(1));

输出:

Macthed: [11111]
Macthed: [22222]
Macthed: [44444-4444]

解释:这个正则表达式使用了前瞻,它本身就像一个条件,这意味着匹配 5 位数字,后面必须跟 - 和 4 位数字或空格或字符串结尾,然后它是可选地匹配文本 - 和 4 位数字。

您的原始 RegEx 引发异常的原因是因为您的 RegEx 的 ?:(?=-) 部分存在语法错误。

【讨论】:

  • 我的主要问题是为什么会出现异常。我想使用条件提取符合指定格式的数字。
  • 实际上,您可以使用"\\d{5}(?:(?=-)-\\d{4})" 修复正则表达式中的异常,但是这只会捕获 44444-4444
  • 但这是否意味着基于前瞻的条件正则表达式在Java中不起作用?否则正确的语法是什么?
  • 我不明白你的正则表达式。(?=(-\\d{4}|\\s|$)) 表示先行查找连字符后跟 4 位数字或空格或字符串结尾?这里的条件在哪里?对不起,我的初始正则表达式都错了?
  • 在您写的同一句话中,您不理解我的正则表达式,然后您正确解释了它。它完全符合您的意图,即 5 位可选地后跟 - 和 4 位。不希望只有一个 -(连字符)的 5 位数字。关于你的正则表达式:是的,它肯定不会像我之前提到的那样编译。
【解决方案2】:

(? 后面缺少一个冒号,即使用此正则表达式(非 Java 字符串):\d{5}(?:(?=-)-\d{4})

但是,这可能仍然不会产生您想要的结果。请发布一些示例输入和所需的输出。

【讨论】:

  • 这只会产生 44444-4444。我期待 11111 22222 44444-4444。所以我的正则表达式(我认为)将匹配前 5 位数字,并且条件前瞻还将包括 @987654326 @ 但不是 33333-,因为条件前瞻将是错误的
【解决方案3】:

你的问题对我来说有点不清楚。我想你正在寻找:

String st = "11111 22222 33333- 44444-4444";
String pattern = "\\d+(- )";
String res  = st.replaceAll(pattern,"");
System.out.println(res);

输出 = 11111 22222 44444-4444

【讨论】:

    【解决方案4】:
    (\d{5}(?!-\s)(?:-\d{4})?)
    

    因此:

    String regex = "(\\d{5}(?!-\\s)(?:-\\d{4})?)";`
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2016-07-12
      • 2019-02-17
      • 1970-01-01
      • 2011-11-08
      相关资源
      最近更新 更多