我正在尝试从Java中的字符串中删除第一次出现的模式。
源字符串:DUMMY01012016DUMMY01012016
格式为1-8个字母数字字符,后跟日期MMddyyyy
,后跟任意数量的字母数字。
想要我想要实现的是删除所有开始的字符,包括第一个日期发生。因此,在下面的示例中,我将留下DUMMY01012016
。
以下是我尝试过的简化版本:".*\\d{4}(2016|2017|2015)"
这种方法很有效,直到模式匹配多次。因此,在示例matcher.replaceFirst("")
中,将替换整个源字符串,而不仅仅是第一次出现。
任何想法都会非常感激。
感谢。斯蒂芬
答案 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)
。然后引擎将执行相反的操作,它将在开头懒惰地匹配并逐个字符地前进。