Разделить текстовый файл Markdown по регулярному выражению, определяющему заголовки
Я пытаюсь использовать программу командной строки, чтобы разбить более крупный текстовый файл на куски с помощью:
- разделить на определенный шаблон регулярного выражения
- имена файлов, определенные группой захвата в этом шаблоне регулярного выражения
Текстовый файл имеет формат:
# Title
# 2020-01-01
Multi-line content
goes here
# 2020-01-02
Other multi-line content
goes here
На выходе должны быть эти два файла со следующими именами файлов и содержимым:
2020-01-01.md ↓
# 2020-01-01
Multi-line content
goes here
2020-01-02.md ↓
# 2020-01-02
Other multi-line content
goes here
Кажется, я не могу правильно уловить все критерии.
Шаблон регулярного выражения для разделения (разделитель) достаточно прост, что-то вроде строк
^# (2020-.*)$
Либо я не могу настроить многострочный шаблон регулярного выражения, который повторяется
\n
новые строки и останавливаются на следующем вхождении шаблона разделителя.
Или я могу расстаться с
csplit
в шаблоне регулярного выражения, но я не могу назвать файлы тем, что записано в
(2020-.*)
То же самое для awk
split()
или
match()
, не могу заставить его работать полностью.
Я ищу общее решение с параметром, являющимся шаблонами регулярных выражений, которые определяют начало фрагмента (например,
# 2020-01-01
) и окончания (например, заголовок следующей даты
# 2020-01-02
или
EOF
)
2 ответа
Используя любой awk в любой оболочке на каждом Unix-компьютере:
$ awk '/^# [0-9]/{ close(out); out=$2".md" } out!=""{print > out}' file
$ head *.md
==> 2020-01-01.md <==
# 2020-01-01
Multi-line content
goes here
==> 2020-01-02.md <==
# 2020-01-02
Other multi-line content
goes here
если
/^# [0-9]/
не является адекватным регулярным выражением, тогда измените его на то, что вам нравится, например
/^# [0-9]{4}(-[0-9]{2}){2}$/
будет более ограничительным. FWIW, хотя я бы вообще не использовал регулярное выражение для этого, если бы вы его не просили. Я бы использовал:
awk '($1=="#") && (c++){ close(out); out=$2".md" } out!=""{print > out}' file
Используя это регулярное выражение , вот Perl для этого:
perl -0777 -nE 'while (/^\h*#\h*(2020.*)([\s\S]*?(?:(?=(^\h*#\h*2020.*))|\z))/gm) {
open($fh, ">", $1.".md") or die $!;
print $fh $1;
print $fh $2;
close $fh;
}' file
результат:
head 2020*
==> 2020-01-01.md <==
2020-01-01
Multi-line content
goes here
==> 2020-01-02.md <==
2020-01-02
Other multi-line content
goes here