регулярное выражение: мультилинии с шаблоном разделительной линии - PullRequest
4 голосов
/ 30 октября 2019

У меня есть этот монстр файла. Его можно разбить на блоки, которые выглядят так:

========
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), но когда я хочу получить содержание , эта часть пуста. Он включается как часть всей группы (если я вызываю match.group () без индекса, но group (3) или group (4) ничего не фиксируют). Что мне там не хватает?

Ответы [ 3 ]

2 голосов
/ 30 октября 2019

Вот один из вариантов:

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 вперед.

1 голос
/ 31 октября 2019

Это работает (?:^=+\n)(^Title: .*\n)(^.*\n)?(?:^=+\n)(((.*\n)(?!=+))+). Вы должны сгруппировать последнюю часть.

1 голос
/ 30 октября 2019

Чтобы получить 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
------
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...