如何在 Linux 计算机上将制表符分隔的文本文件中的空行替换为上面行的内容?例如:
101 abc group1
765 efg group2
345 hij group4
456 gfd group9
762 ert group7
554 fgt group11
预期输出:
101 abc group1
765 efg group2
345 hij group3
345 hij group3
456 gfd group9
762 ert group7
762 ert group7
762 ert group7
554 fgt group11
答案1
这是一种方法awk
(当为零p
时保留前一行)。NF
awk 'NF {p = $0} {print p}' file
当该行不为空时,我们将该行存储到p
(以供将来使用)并打印p
。
当NF==0
(对于空行)我们只打印p
.
答案2
在awk
(请注意,这将打印第一个非空行之前的所有空行):
$ awk '{ if(! NF){$0=last}else{last=$0;}}1' file
101 abc group1
765 efg group2
345 hij group4
345 hij group4
456 gfd group9
762 ert group7
762 ert group7
762 ert group7
554 fgt group11
解释:
NF
保存字段的数量。如果该行为空,则没有字段,因此变量将为0
。
if(! NF){$0=last}
:如果字段数为 0(空行),则将当前行 ($0
) 设置为变量 的值last
。else{last=$0;}
:如果有字段,那么这一行不为空,设置last
为保存这一行的内容。1
:最后唯一的一个是 awk 技巧:当某项计算结果为 true(1 或任何其他大于 0 的整数始终为 true,因为 0 为 false)时,awk 将打印当前行。所以这1
相当于print $0
.
$ awk '! NF ? $0=last : last=$0;' file
101 abc group1
765 efg group2
345 hij group4
345 hij group4
456 gfd group9
762 ert group7
762 ert group7
762 ert group7
554 fgt group11
解释
这与上面的想法相同,但以更简洁的方式编写。我们正在使用三元运算符。由于两个条件之一始终为真(要么NF
为真,要么不为真,因此三元运算符将始终返回 true),因此两种结果都会导致打印该行(除非该行为空且没有非- 已看到空行或行仅由0
) 组成。但是,如果NF
未设置,我们设置$0
为last
;如果设置了,我们设置last
为$0
。结果就是我们想要的输出。
由于上面不会打印只是 的行0
,因此您可以使用 this 而不是 that 对您来说是一个问题:
awk '{! NF ? $0=last : last=$0};1' file
答案3
使用提供的输入和sed
:
$ sed -n '/^$/{g;};h;p' infile
101 abc group1
765 efg group2
345 hij group4
345 hij group4
456 gfd group9
762 ert group7
762 ert group7
762 ert group7
554 fgt group11
$
注意:'/^$/{g;};h;p'
显然更常见/正确地写为'/^$/g;h;p'
.只是我的风格!
正如guest_7
所指出的(谢谢),该sed
命令也可以更简单地写为sed '/^$/g;h' infile
正如所terdon
指出的,我最初没有想到的是,“空”行可能包含空格或制表符(空白)。在这种情况下,更可靠的解决方案是:
$ sed '/^\s*$/g;h' infile
支持各种语言环境的更便携的解决方案是:
$ sed '/^[[:blank:]]*$/g;h' infile
答案4
添加到现有答案:
awk 'NR<2 && !NF{next} NF{print} !NF{print line} NF{line=$0}' test
...还将处理空的第一行(通过忽略它,因为它没有先前的输入)。