[英]SED: delete lines after pattern match while skipping a few lines, then delete the pattern line
假设我要删除模式后的某些行,同时跳过它们之间的某些行,然后删除具有模式本身的行。 我可以使用以下两个命令来执行此操作:
sed -i '/PATTERN/{n;n;n;n;n;n;N;N;N;N;d}' file # match pattern, skip 5 lines, then delete 5 consecutive lines
sed -i /PATTERN/d file # delete line with pattern
但是我想用一个命令来完成。 这里的问题很明显,因为模式更改会影响两个表达式,因此更改必须在单个表达式中指定。 有没有办法做到这一点?
更新:
输入示例:
...
ifeq ($(ose),)
dh_installdocs \
$(archdir)/UserManual*.pdf $(archdir)/VirtualBox*.chm \
$(addprefix $(archdir)/, LICENSE)
rm $(addprefix $(archdir)/,UserManual*.pdf VirtualBox*.chm \
LICENSE)
else
dh_installdocs \
$(archdir)/UserManual*.pdf
rm $(addprefix $(archdir)/,UserManual*.pdf)
endif
...
输出示例:
...
dh_installdocs \
$(archdir)/UserManual*.pdf $(archdir)/VirtualBox*.chm \
$(addprefix $(archdir)/, LICENSE)
rm $(addprefix $(archdir)/,UserManual*.pdf VirtualBox*.chm \
LICENSE)
...
更新2:
可以从以下位置获取示例文件: http : //download.virtualbox.org/virtualbox/5.0.4/VirtualBox-5.0.4.tar.bz2 ( debian / rules )
敬请解救!
awk 's&&s--{print;next} d&&d--{next} /pattern/{d=5;s=5;next} 1'
使用Ed Morton的智能计数器将s设置为跳过,将d设置为删除
对于您的模式,您需要转义特殊字符
awk 's&&s--{print;next} d&&d--{next} /\(\$\(ose\),\)/{d=5;s=5;next} 1'
如果不需要sed
我将提供perl
可以在“ sed模式”下工作,并使用正则表达式以及一些更复杂的脚本逻辑。
例如for循环:
#!/usr/bin/env perl
use strict;
use warnings;
while ( <DATA> ) {
if ( m/ifeq\ \(\$\(ose\)\,\)/ ) {
print "". <DATA> for 1..5;
<DATA> for ( 1..5 );
}
else { print };
}
__DATA__
...
ifeq ($(ose),)
dh_installdocs \
$(archdir)/UserManual*.pdf $(archdir)/VirtualBox*.chm \
$(addprefix $(archdir)/, LICENSE)
rm $(addprefix $(archdir)/,UserManual*.pdf VirtualBox*.chm \
LICENSE)
else
dh_installdocs \
$(archdir)/UserManual*.pdf
rm $(addprefix $(archdir)/,UserManual*.pdf)
endif
...
您可以像sed一样“内联”:
perl -i -ne 'if ( m/ifeq\ \(\$\(ose\)\,\)/ ) { print "". <> for 1..5; <> for ( 1..5 );} else {print}'
另外,您可以使用perl的“范围运算符”来检测您是否处于两种模式之间。 不过,这更多地取决于文件的其余部分(我认为'else'...'endif'并不罕见)。
这是使用awk的一种方法:
awk '/ifeq/ { n = 6; next } n && !--n { c = 1 } c && c++ < 6 { next }1' file
看起来有些棘手,但逻辑如下:
/ifeq/
模式匹配时,将变量n
设置为6并跳过该行 n && !--n
仅在n
为1时才为真(以这种方式写入,因此n
仅在减至0之前递减) c
,跳过每一行,直到c
达到6 1
表示将打印任何未跳过的行(默认操作是 { print }
。 另一种方法:
sed '/($(ose),)/,/^endif/{/($(ose),)/d;/^else/,/^endif/d}' file
输出:
... dh_installdocs \ $(archdir)/UserManual*.pdf $(archdir)/VirtualBox*.chm \ $(addprefix $(archdir)/, LICENSE) rm $(addprefix $(archdir)/,UserManual*.pdf VirtualBox*.chm \ LICENSE) ...
添加选项-i
以“就地”编辑。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.