匹配Java中分隔符之间的多行文本

时间:2014-09-03 23:13:58

标签: java regex multiline

如何在Java中的分隔符之间匹配多行文本?

问题最好通过一个例子解释:

...
unimportant text
EndOfEntry
Key=Value
unimportant text
maybe a few lines of unimportant text
AnotherKey=AnotherValue
EndOfEntry
more unimportant text
...

在上面,我想匹配Key = Value。* AnotherKey = AnotherValue一起出现在一个条目中。我只想知道模式是否出现 - 我不需要更换任何东西。

但是,如果给定多个条目,则使用相同的所需匹配,例如:

...
unimportant text
EndOfEntry
Key=Value
unimportant text
maybe a few lines of unimportant text
AnotherKey=NotMyValue
EndOfEntry
RandomKey=Value
unimportant text
maybe a few lines of unimportant text
AnotherKey=AnotherValue
EndOfEntry
more unimportant text
...

我不希望上述内容成功匹配,因为我们在单个"条目"中没有看到确切的Key = Value和AnotherKey = AnotherValue。相反,我们在第一个条目中看到Key = Value,在第二个条目中看到AnotherKey = AnotherValue。

我一直尝试使用正则表达式(当然\ S \ s可以替换为Pattern的DOTALL选项):

Key=Value[\S\s]*?AnotherKey=AnotherValue

但当然这两者都匹配。我也试过了:

Key=Value[^EndOfEntry]*?AnotherKey=AnotherValue

但这不起作用,因为那时没有点,我们根本不匹配新行。

是否有一个正则表达式可以精确匹配我正在寻找的东西?它是否会简化首先删除换行符或其他两步处理的事情(我只是为了教育而试图避免)?

1 个答案:

答案 0 :(得分:2)

您应该使用:

\bKey=Value\b(?:(?!EndOfEntry).)*?\bAnotherKey=AnotherValue\b

(使用 DOTALL 标记,如您在问题中所建议的那样)。

实验室实验here on regex101


工作原理:

我基本上只是将.*替换为((?!EndOfEntry).)*,表示大致任何不包含EndOfEntry 的内容。

此外,为了避免与对RandomKey=ValueAnotherKey=AnotherValue匹配,由于RandomKey=Value也会匹配Key=Value(例如),我添加了另一个调整:

我用\b包围你的对(断言我们在一个单词边界)(或\s,对于任何空格字符),所以我们只有一个匹配时整个单词都是匹配的。


这是一段 Java 代码,它使用我建议的正则表达式反对你的例子:

final Pattern pattern = Pattern.compile("\\bKey=Value\\b(?:(?!EndOfEntry).)*?\\bAnotherKey=AnotherValue\\b", Pattern.DOTALL);

final String invalid = "unimportant text\n" +
                "EndOfEntry\n" +
                "Key=Value\n" +
                "unimportant text\n" +
                "maybe a few lines of unimportant text\n" +
                "AnotherKey=NotMyValue\n" +
                "EndOfEntry\n" +
                "RandomKey=Value\n" +
                "unimportant text\n" +
                "maybe a few lines of unimportant text\n" +
                "AnotherKey=AnotherValue\n" +
                "EndOfEntry\n" +
                "more unimportant text";

final String valid = "unimportant text\n" +
                "EndOfEntry\n" +
                "Key=Value\n" +
                "unimportant text\n" +
                "maybe a few lines of unimportant text\n" +
                "AnotherKey=AnotherValue\n" +
                "EndOfEntry\n" +
                "more unimportant text";

System.out.println(pattern.matcher(invalid).find());
System.out.println(pattern.matcher(valid).find());

输出:

false
true