如果没有换行符,请在与模式匹配的行之前创建换行符

时间:2018-08-27 15:25:10

标签: linux bash shell sed

我有一个文本文件,其中有几行。我想做的是找到所有与模式匹配的行,如果在它们之前没有换行符(=非空行),请创建它。 这样的东西,但是不能正常工作:

sed -i '/[a-zA-Z0-9]/{N;/PATTERN/{s/PATTERN/\nPATTERN/}}' FILENAME

我知道用awk或perl / bash可以更轻松,更轻松地完成此操作,但是我更喜欢单行/一步的解决方案。

样本输入文件:

LINE1
LINE2
PATTERN
LINE3

PATTERN
LINE4

预期输出:

LINE1
LINE2

PATTERN
LINE3

PATTERN
LINE4

2 个答案:

答案 0 :(得分:1)

我不太擅长sed,但是这是我在awk中的方法:

awk 'prev != "" && /PATTERN/ { print "" } { prev = $0; print }' file

如果prev(上一行)不为空并且当前行与/PATTERN/相匹配,则打印空白行。无条件地保存当前行以便与下一行以及print当前行进行比较。

要实现“就地”编辑(如sed -i),只需将命令重定向到一个临时文件,然后覆盖原始文件:

awk 'prev != "" && /PATTERN/ { print "" } { prev = $0; print }' file > tmp && mv tmp file

请注意,由于最初未设置prev,因此即使第一行与/PATTERN/相匹配,此也不会在输出的开头打印换行符。要解决此问题,您可以将条件更改为:

(NR == 1 || prev != "") && /PATTERN/

您还可以使用-i inplace选项,使用GNU awk实现就地编辑。

答案 1 :(得分:1)

看看这个GNU sed(注意,awk是工作的更好工具):

sed -i '/PATTERN/{x;/^$/!i\

x};h' input
  • h是将模式空间的内容保存到保持缓冲区的命令。它将在每个循环结束时保存该行,以便在下一个循环中将其用作“上一个”行

  • x交换保留空间和模式空间的内容。只要当前行与您的/PATTERN/相匹配,就会将先前保存的行放入模式空间。如果前一行 NOT 为空(/^$/!),则使用i命令插入换行符。然后使用x命令将当前行放回模式空间

  • 如果即使第一行与/PATTERN/相匹配,也要添加换行符,请使用:

    sed -i '/PATTERN/{1h;x;/^$/! ...
    

进一步阅读: