我有很多 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
更改,p
为w
会将修改后的缓冲区写回到原始文件中。
类似的解决方案使用sed
:
sed -e 1b -e '/^* / i\
' file
...或者,使用 GNU sed
:
sed -e 1b -e '/^* / i \\' file
分支b
(跳转)到给定标签,或者如果没有标签则跳转到脚本末尾。我们在这里使用它来显式地对第一行不执行任何操作。然后,我们应用一个插入命令,在所有以 开头的行前面添加一个空行*
。