在包含某些字符的每一行之前添加空行

在包含某些字符的每一行之前添加空行

我有很多 Markdown 文件,其中包含以下内容:

* header A  
- item 1  
- item 2
** sub-header A1
** sub-header A2   
* header B  
- item 1  
- item 2  
** sub-header B1
** sub-header B2  
* header C  
- item 1  
- item 2 
** sub-header C1
** sub-header C2  

我想改变它们,使内容变成这样:

* header A  
- item 1  
- item 2
** sub-header A1
** sub-header A2   

* header B  
- item 1  
- item 2  
** sub-header B1
** sub-header B2  

* header C  
- item 1  
- item 2 
** sub-header C1
** sub-header C2  

因此,基本上,脚本应该处理单个文件,并在除第一行之外的仅包含一个星号的每一行之前添加一个新行。

另外,我想要第二个脚本几乎与第一个脚本相同,但它与其中包含任意数量星号的行相匹配,所以如果我有这个:

* header A  
- item 1  
- item 2
** sub-header A1
** sub-header A2   
* header B  
- item 1  
- item 2  
** sub-header B1
** sub-header B2  
* header C  
- item 1  
- item 2 
** sub-header C1
** sub-header C2  

我想把它改成:

* header A  
- item 1  
- item 2

** sub-header A1

** sub-header A2
   
* header B  
- item 1  
- item 2  

** sub-header B1

** sub-header B2  

* header C  
- item 1  
- item 2 

** sub-header C1

** sub-header C2  

答案1

perl

perl -i -ple 'print "" if $. > 1 && /^\s*\*(\*+|[^*]*)\s*/' your-file

将以任意数量的空格开头的任何行(第一行除外)之前打印一个空行,然后打印*1 个或多个附加的空行*,或者不打印任何其他*行,直到最后允许空格。因此,要么是由多个行组成的行,要么是开头*只有一个且只有一个的行(可以选择前面有空格,后面可以跟任何内容)。*

使用-i,文件就地编辑。

如果处理多个文件,您需要close ARGV if eof确保$.在每个文件后重置为 1:

perl -i -ple '
  print "" if $. > 1 && /^\s*\*(\*+|[^*]*)\s*/;
  close ARGV if eof' ./*.md

答案2

另一种 perl 方法:

$ perl -ne 'print /^\*[^*]*$/ && $. > 1 ? "\n$_" : "$_"' file
* header A  
- item 1  
- item 2   

* header B  
- item 1  
- item 2  

* header C  
- item 1  
- item 2 

这将在以第一行开头并且除第一行之外*不包含任何其他位置的每一行之前打印换行符。*

答案3

一种可能的解决方案是使用awk.类似的东西可以完成这项工作:

 awk '/^*/ { if (FNR!=1) printf "\n"} {print $0}' <input file>

这个想法是搜索以 开头的记录*并检查这是否不是第一个记录。如果两个条件都满足,则打印空行。然后打印输入行。

简化版本,在评论中提供:

awk 'FNR > 1 && /^*/ {printf "\n"} 1'

*PS 该脚本仅在文件中的第一个位置上没有问题。

答案4

使用编辑脚本,从第 2 行开始,ed在以字符串 开头的每一行插入一个空行:*

2,$ g/^* / i \
\
.

g命令应用于从 2 到最后一行 ( $) 的所有行,并且它应用一个i(“插入”)命令,该命令在与正则表达式 匹配的行前面添加一个空行^*。使用^*\**或来匹配行开头^*\{1,\}的任意非零个数。*

i命令看起来有点奇怪,但它只是

i

.

(即插入一个空行),但是自从我们通过命令执行它以来,我们必须转义除最后一行之外的所有行上的换行符g

如果您不想开始查找以 开头的行*,而是开始查找以 开头的行*,则可以将命令中的 更改2为跳过第一*行的内容,例如/^* /+1

在给定的数据上运行它,使用几个额外的命令打印出修改后的缓冲区并退出而不保存:

$ printf '%s\n' '2,$ g/^* / i\' '\' . ,p Q | ed -s file
* header A
- item 1
- item 2

* header B
- item 1
- item 2

* header C
- item 1
- item 2

更改,pw会将修改后的缓冲区写回到原始文件中。


类似的解决方案使用sed

sed -e 1b -e '/^* / i\

' file

...或者,使用 GNU sed

sed -e 1b -e '/^* / i \\' file

分支b(跳转)到给定标签,或者如果没有标签则跳转到脚本末尾。我们在这里使用它来显式地对第一行不执行任何操作。然后,我们应用一个插入命令,在所有以 开头的行前面添加一个空行*

相关内容