Java多次匹配同一组

时间:2016-10-31 09:35:01

标签: java regex

我需要多次匹配相同模式的字符序列。

例如:对于输入Some words <firstMatch> some words <secondMatch> some more words <ThirdMatch>,我需要<firstMatch><secondMatch><thirdMatch>

我尝试过这样的事情:

String input = "Some words <firstMatch> some words <secondMatch> some more words <ThirdMatch>";
Pattern pattern = Pattern.compile( ".*(\\<.*\\>).*" );
Matcher m = pattern.matcher( input );
while ( m.find() ) {
         System.out.println( m.group( 1 ) );
}

我得到的只是ThirdMatch

任何帮助?

4 个答案:

答案 0 :(得分:4)

为什么您的模式会失败?

.*(\\<.*\\>).*会引发很多回溯。首先,.*匹配除了换行符之外的任何0+字符,基本上是整行。然后,正则表达式引擎回溯试图适应后续模式(<.*>).*。当它找到<(从头到尾)时,它将再次抓住整行,并继续回溯搜索>。找到后,最后一个.*只匹配该行的其余部分。请注意,如果引擎在>之后未能找到<,则回溯将重复搜索,从而使此模式效率低下。注意:<>不必以Java正则表达式模式进行转义,它们不是特殊的正则表达式元字符。

<强>解决方案

使用基于negated character class的简单"<[^>]*>"模式:

String input = "Some words <firstMatch> some words <secondMatch> some more words <ThirdMatch>";
Pattern pattern = Pattern.compile( "<[^>]*>" );
Matcher m = pattern.matcher( input );
while ( m.find() ) {
   System.out.println( m.group(0) ); // = m.group(), the whole match value
}

请参阅Java demo

<[^>]*>将匹配<,除>以外的0 +字符,然后>。由于您在Matcher#find()块中使用while,因此您会在输入字符串中找到所有非重叠匹配项,但您需要访问.group(0)(等于.group(),整个匹配值),而不是.group(1)

答案 1 :(得分:2)

您可以使用正则表达式

[^<]*<([^>]*)>

测试字符串

Some words <firstMatch> some words <secondMatch> some more words <ThirdMatch>

匹配字符串

Match 1
Group 1.    12-22   `firstMatch`
Match 2
Group 1.    36-47   `secondMatch`
Match 3
Group 1.    66-76   `ThirdMatch`

DEMO

答案 2 :(得分:1)

.*greedy - 它会匹配下一个模式的最终匹配所能提供的所有内容...您可以通过在{{1}之后添加问号来使其变得非贪婪}符号如此匹配任何字符,任何次数,而不是贪婪将是*,你的模式将是:

.*?

然而,这只会让你到达那里。如果你知道你的模式匹配了多少次,你可以把它放到你的模式中,例如

Pattern pattern = Pattern.compile( ".*?(\\<.*\\>).*?" );

三场比赛。

答案 3 :(得分:1)

你去:)

while(std::getline)