正则表达式模式的问题

时间:2016-04-14 18:47:20

标签: java regex

我正在尝试从Java中的字符串中删除第一次出现的模式。

源字符串:DUMMY01012016DUMMY01012016

格式为1-8个字母数字字符,后跟日期MMddyyyy,后跟任意数量的字母数字。

想要我想要实现的是删除所有开始的字符,包括第一个日期发生。因此,在下面的示例中,我将留下DUMMY01012016

以下是我尝试过的简化版本:".*\\d{4}(2016|2017|2015)"

这种方法很有效,直到模式匹配多次。因此,在示例matcher.replaceFirst("")中,将替换整个源字符串,而不仅仅是第一次出现。

任何想法都会非常感激。

感谢。斯蒂芬

3 个答案:

答案 0 :(得分:1)

您的问题是*量词是贪婪的。它将使前面的子模式尽可能多地匹配,而不会导致整体匹配失败(如果匹配完全可能)。因此,模式.*\d{4}(2016|2017|2015)的尾部将匹配字符串中最后一次出现的日期,而您希望它与第一次匹配。

您可以通过切换到“不情愿”量词来解决此问题:

myString.replaceFirst(".*?\d{4}(2016|2017|2015)", "");

在那里,*?是一个不情愿的量词:它匹配前一个子模式的零个或多个实例,尽可能几个以启用整体匹配(如果整体匹配是可能的)。

答案 1 :(得分:0)

这个正则表达式应该有效:

(\w{1,8}?\d{8})(?:\1)

答案 2 :(得分:0)

您的一个问题是.* 贪婪。这意味着它首先匹配尽可能多的匹配。然后,正则表达式引擎开始逐个符号退回,直到找到完全匹配。

所以,粗略地说:

步骤1).*对整个DUMMY01012016DUMMY01012016

进行定位

步骤2)引擎逐个符号地逐步退回以尝试匹配剩余部分: DUMMY01012016DUMMY0101201 - > DUMMY01012016DUMMY010120 - > DUMMY01012016DUMMY01012 - > .. - > DUMMY01012016DUMMY

步骤3)找到完全匹配 - > DUMMY01012016DUMMY01012016

您可以尝试这样的事情:

@Test
public void testReplace()
{
    String string = "DUMMY01012016DUMMY01012016";

    String replaced = string.replaceFirst("\\w{1,8}\\d{4}(2016|2017|2015)", "");

    Assert.assertEquals("DUMMY01012016", replaced);
}

要了解懒惰和贪婪之间的区别,您可以通过添加问号?进行实验并使星号变得懒惰。 .*?\d{4}(2016|2017|2015)。然后引擎将执行相反的操作,它将在开头懒惰地匹配并逐个字符地前进。