1

我正在尝试使用命令行程序将较大的文本文件拆分为块:

  • 拆分定义的正则表达式模式
  • 由该正则表达式模式中的捕获组定义的文件名

文本文件的格式为:

# Title

# 2020-01-01

Multi-line content
goes here

# 2020-01-02

Other multi-line content
goes here

输出应该是具有以下文件名和内容的这两个文件:

2020-01-01.md ↓</p>

# 2020-01-01

Multi-line content
goes here

2020-01-02.md ↓</p>

# 2020-01-02

Other multi-line content
goes here

我似乎无法正确掌握所有标准。

要拆分的正则表达式模式(分隔符)很简单,类似于^# (2020-.*)$

要么我无法设置一个多行正则表达式模式,它会越过\n换行符并在下一次出现分隔符模式时停止。

或者我可以在正则表达式模式上拆分csplit,但我不能用捕获的内容命名文件(2020-.*)

awk split()or也一样match(),不能让它完全工作。

我正在寻找一个通用的解决方案,参数是定义块开始(例如# 2020-01-01)和结束(例如下一个日期标题# 2020-01-02EOF)的正则表达式模式

4

2 回答 2

1

在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ 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
于 2021-09-02T21:20:45.280 回答
1

使用这个正则表达式,这里有一个 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
于 2021-09-02T21:18:16.417 回答