2016-04-14 221 views
0

我想从Java中的字符串中删除第一次出现的模式。正则表达式模式的问题

来源字符串:DUMMY01012016DUMMY01012016

格式是1-8的字母数字字符,后面跟随任意数目字母数字的日期MMddyyyy

想要实现的是删除所有开头的字符,包括第一次发生的日期。所以在下面的例子中,我将留下DUMMY01012016

这里是什么,我已经尝试了简化版本:".*\\d{4}(2016|2017|2015)"

直到模式匹配不止一次效果很好。因此在示例matcher.replaceFirst("")将会替换整个源字符串,而不仅仅是第一次出现。

任何想法将不胜感激。

谢谢。斯蒂芬

+0

'。\ d {4}(2016 | 2017 | 2015)。?'如何匹配您的模式?这不符合_1-8字母数字字符的格式,后跟日期MMddyyyy,后跟任意数量的字母数字。 – 2016-04-14 18:50:02

+0

[使用正则表达式获取字符串中模式的索引]可能的重复(http://stackoverflow.com/questions/8938498/get-the-index-of-a-pattern-in-a-string-using-正则表达式) – flakes

+0

“字母数字字符”你真的是指*字母*字符,即字母? “字母数字”包括数字。 –

回答

0

此正则表达式应该工作:

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

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

所以,大致为:

步骤1).* macthes整个DUMMY01012016DUMMY01012016

步骤2)所述的发动机用符号试图其余部分相匹配的步骤后退符号: - >DUMMY01012016DUMMY010120 - >DUMMY01012016DUMMY01012 DUMMY01012016DUMMY0101201 - > .. - >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)。然后引擎会做相反的事情,它会在开始时懒惰地匹配,并逐个字符地前进。

1

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

您可以通过切换到“不情愿”的量词,而不是解决这个问题:

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

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