regex:具有分隔线图案的多行

问题描述 投票:2回答:2

我有这个文件的怪物。可以将其拆分为如下所示的块:

========
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.compilePattern.MULTILINE),但是当我想获得content时,那部分是空的。它被包含为整个组的一部分(如果我调用match.group()时没有索引,但是group(3)或group(4)无法捕获任何内容)。我在那里想念什么?

java regex multiline
2个回答
1
投票

这里是一种选择:

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在结果数组中向前。


0
投票

要获得titlesubtitle 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
------
© www.soinside.com 2019 - 2024. All rights reserved.