我有这个文件的怪物。可以将其拆分为如下所示的块:
========
Title: title 1
optional subtitle
====
content 1
content 2
content 3
====
Title: title 2
========
content 4
content 5
content 6
所以,我们在那里有两个街区,对吧?
我正在尝试分割成这样的东西:
(?:^=+\n)(^Title: .*\n)(^.*\n)?(?:^=+\n)((.*\n)(?!=+))+
现在,我可以看到两个组被很好地分开了,我得到了两个组(顺便说一下,这是在Java中,使用Pattern.compile
和Pattern.MULTILINE
),但是当我想获得content时,那部分是空的。它被包含为整个组的一部分(如果我调用match.group()时没有索引,但是group(3)或group(4)无法捕获任何内容)。我在那里想念什么?
这里是一种选择:
String input = "========\nTitle: title 1\noptional subtitle\n====\ncontent 1\ncontent 2\n\ncontent 3\n\n====\nTitle: title 2\n========\ncontent 4\ncontent 5\ncontent 6";
String[] parts = input.split("(?s)=+\nTitle:.*?\n=+");
for (int i=1; i < parts.length; ++i) {
System.out.println("PART " + i + ":");
System.out.println(parts[i]);
}
此打印:
PART 1:
content 1
content 2
content 3
PART 2:
content 4
content 5
content 6
[请注意,在进行正则表达式拆分时,我使用(?s)
标志,以确保点可以在换行符之间匹配(即,我使用DOT ALL模式)。另外,我忽略了数组中的第一个空元素,这是因为文件以分隔符开头。也就是说,我们只希望元素2在结果数组中向前。
要获得title
,subtitle
,和 content
,并且不必在正则表达式中重复太多(更简单和更好的性能),我可以通过匹配标头来实现,手动捕获内容。
允许内容包含与完整标题不匹配的任何文本。
public class Section {
private final String title;
private final String subtitle;
private String content;
public Section(String title, String subtitle) {
this.title = title;
this.subtitle = subtitle;
}
public void setContent(String content) {
this.content = content;
}
public String getTitle() {
return this.title;
}
public String getSubtitle() {
return this.subtitle;
}
public String getContent() {
return this.content;
}
public static List<Section> parse(String fileContent) {
List<Section> sections = new ArrayList<>();
Section section = null;
int start = 0;
final String regex = "(?m)^=+\\RTitle: (.*)\\R(?:(?!=)(.*)\\R)?=+\\R";
for (Matcher m = Pattern.compile(regex).matcher(fileContent); m.find(); ) {
if (section != null)
section.setContent(fileContent.substring(start, m.start()).stripTrailing());
section = new Section(m.group(1), m.group(2));
sections.add(section);
start = m.end();
}
if (section != null)
section.setContent(fileContent.substring(start).stripTrailing());
return sections;
}
}
Test
String fileContent = Files.readString(Paths.get("Test.txt"));
List<Section> sections = Section.parse(fileContent);
for (Section section : sections) {
System.out.println("Title: " + section.getTitle());
if (section.getSubtitle() != null)
System.out.println("Subtitle: " + section.getSubtitle());
System.out.println(section.getContent());
System.out.println("------");
}
输出
Title: title 1
Subtitle: optional subtitle
content 1
content 2
content 3
------
Title: title 2
content 4
content 5
content 6
------