如何在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
但这不起作用,因为那时没有点,我们根本不匹配新行。
是否有一个正则表达式可以精确匹配我正在寻找的东西?它是否会简化首先删除换行符或其他两步处理的事情(我只是为了教育而试图避免)?
答案 0 :(得分:2)
您应该使用:
\bKey=Value\b(?:(?!EndOfEntry).)*?\bAnotherKey=AnotherValue\b
(使用 DOTALL 标记,如您在问题中所建议的那样)。
实验室实验here on regex101。
工作原理:
我基本上只是将.*
替换为((?!EndOfEntry).)*
,表示大致任何不包含EndOfEntry
的内容。
此外,为了避免与对RandomKey=Value
和AnotherKey=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