如何从第5行开始删除空白行


10

我有这个:

sed -i '/^$/d' temp_spec.rb

这将删除空白行,并且效果很好。我如何才能仅对5-999行执行此操作(最好是在文件末尾添加5行)。

我试过了:

sed -n5,999 -i '/^$/d' temp_spec.rb
sed '5,999!d/^$/d' temp_spec.rb

但均无效(无错误)。


只需确定一下:是否要保留第1至4行,无论它们是否为空白,还是要删除第1至4行,无论它们是否为空白?(到目前为止,我假设是前者,但是您尝试的第二个命令使我感到奇怪。)
Uwe

Answers:


12

如果要删除从第5行开始的所有空白行,并保留第1至4行,则可以使用

sed -i '5,${;/^$/d;}' temp_spec.rb

由于{是分组运算符,因此第一个命令的5,${意思是“从第5行到输入($)的末尾执行以下命令,直到匹配}”。{和之间的命令}可以再次加上地址前缀,因此内部命令的/^$/d意思是“如果该行的开始(^)和结束($)之间没有任何内容,则将其删除”。sed命令可以用分隔;。(这是sed的一个文献记录不清的功能。大多数sed实现都支持此功能,但它并不是完全可移植的。)正如Hauke所指出的,;after {是可选的;不过,这}是必需的。

如果要删除从第5行开始的所有空白行,并且还删除第1至4行,则比较容易:

sed -i '1,4d;/^$/d' temp_spec.rb

真好 我不知道地址可以这样嵌套。对我来说,它也不需要领导;
Hauke Laging

是的,您对第一个是正确的;
Uwe

@Hauke Laging您可以在sed脚本中用';'分隔命令。而是将它们放在单独的行上。这是“未记录”的功能。
Predrag Punosevac

4

使用awk的另一种选择:

awk 'NR<5||/./'

2
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb

编辑1:

我应该解释一下,因此...

这不必要地复杂。我不知道内的地址范围是允许的{}。因此,我不得不用不同的方式表达“删除空白行”。核心命令是tsed的方式if ... thenT本来会更容易,但仅适用于GNU sed。我引用了手册页:

t label:如果自从最后一条输入行被读取以来以及从最后一个t或T命令以来,as ///已成功完成替换,则跳转到label;如果省略了label,则跳转到脚本结尾。

我滥用了著名的s命令。它不能替代任何东西,而只能测试行是否为空。因此,它将用空行替换空行(无论如何删除行都可以使用任何东西作为替换)。

如果执行s了“替换”,则该行为空。在这种情况下,d应执行命令。否则,什么都不做。因为在t执行操作时不会跳转,所以s我需要使用branch命令b跳转到脚本的末尾。: label是分支目标。就像goto在黑暗时代(当sed发明时…te-hee)一样。

另一种选择是s“替换”所有非空行,使s更复杂但其余部分的命令更容易:

sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input

^..*$表示“非空行”,\1表示“第一个括号的内容”。


出于OP的缘故的一些解释(我能感觉到他们的大脑正试图从耳朵里爬出来,阅读这篇文章...)
vonbrand
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.