我有这个:
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
如果要删除从第5行开始的所有空白行并保留第1行到第4行,可以使用
sed -i '5,${;/^$/d;}' temp_spec.rb
是{
分组运算符,所以第一条命令的5,${
意思是“从第5行到input( $
)结束执行以下命令,直到匹配}
”。{
和之间的命令}
也可以用地址作为前缀,因此内部命令的意思是“如果该行的开头 ( ) 和结尾 ( )/^$/d
之间没有任何内容,则删除它”。 sed 命令可以用 分隔。 (这是 sed 的一个记录很差的功能。大多数 sed 实现都支持它,但它是^
$
;
不完全便携.) 正如 Hauke 所指出的,;
后面的内容{
是可选的;不过,前面的那个}
是必需的。
如果要删除从第 5 行开始的所有空白行,并删除第 1 至 4 行,则更容易:
sed -i '1,4d;/^$/d' temp_spec.rb
答案2
使用 awk 的另一个选项:
awk 'NR<5||/./'
答案3
sed '5,${s/^$//; t delete; b end; : delete; d; : end;}' temp_spec.rb
编辑1:
我应该解释一下这一点,因此......
这不必要地复杂。我不知道{}
.所以我必须以不同的方式表达“删除空行”。核心命令是t
which 是 sed 的方式if ... then
。T
本来会更容易,但仅适用于 GNU sed。我引用手册页:
t label :如果自上次读取输入行以来以及自上次 t 或 T 命令以来 as/// 已成功替换,则分支到 label;如果省略标签,则分支到脚本末尾。
我滥用了著名的s
命令。它不会替换任何内容,而仅测试该行是否为空。因此,它用空行替换空行(可以使用任何内容作为替换,因为无论如何该行都会被删除)。
如果s
已完成“替换”,则该行为空。在这种情况下,d
应执行该命令。否则什么也不能做。由于t
在执行操作时不会跳转,s
我需要分支命令b
跳转到脚本的末尾。: label
是分支目标。就像goto
在黑暗时代那样(当 sed 被发明时...... te-hee)。
另一种选择是s
“替换”所有非空行,使s
命令更复杂,但其余部分更容易:
sed '5,${s/^\(..*\)$/\1/; t end; d; : end;}' input
^..*$
表示“非空行”,\1
表示“第一个括号的内容”。