我需要在 csh 中编写一个 shell 脚本来搜索和删除与模式匹配的行以及前一行的注释(如果有)。例如,如果我的文件有以下几行
Shell 脚本 #这是一个测试 模式1 格式1 模式2 格式2 #格式3 模式3
如果搜索模式是“pattern”,则输出应如下所示
Shell 脚本 格式1 格式2
更准确地说,应该删除包含模式的行以及以“#”开头的上一行
谢谢您的帮助
答案1
首先任何人都不应该使用csh
对于任何事来说,它都过时了,而且功能不够强大(不是“不足”)。其次,我怀疑它能否胜任这项任务。第三,更有可能的是awk
,sed
甚至 Perl 将成为完成这项任务的更好的工具。
awk '/^#/ {printf line; line=$0"\n"; next} /pattern/ {line=""} ! /pattern/ {printf line; print; line=""}'
编辑:修复脚本以正确处理注释行
答案2
这是 Perl 中的一行解决方案(不是 C shell)。您可以修改/pattern/
中间的正则表达式。
perl -ne 'if(/^#/){$c=$_}elsif(!/pattern/){print$c,$_;$c=""}else{$c=""}' <file.in
答案3
从逻辑上来说,可能这是一种更好的写法,但我认为这可以做到这一点:
#!/usr/bin/perl
use strict;
use warnings;
my $previous_line = '';
while(<>) {
if ( /pattern/ ) {
if ( (! ($previous_line =~ /^#/)) && (! ($previous_line =~ /pattern/))) {
print $previous_line;
}
} elsif (! ($previous_line =~ /pattern/)) {
print $previous_line;
}
$previous_line = $_;
}
print $previous_line if not ($previous_line =~ /pattern/);
基本上,循环是上一行后面的一行。它表示可以打印上一行如果:
- 如果当前行与模式匹配:只要前一行也不与模式匹配,或者是注释,就可以打印前一行。
- 如果这一行不是模式,那么只要它与模式不匹配,就可以打印前一行。
您可以将代码保存在文件中并按如下方式使用它:perl thefile.pl textfile_you_want_to_filter
答案4
它必须是 shell 脚本吗?
- 使用 vi 打开文件
:g/<pattern>/d
- 根据需要重复添加其他模式类型,除非你可以用正则表达式表达模式
:g/^#/d
如果必须编写脚本,可以使用 sed 有效地重现
编辑:
1.创建文件.sedscript:
/pattern/d
/^#/d
2.sed -f .sedscript <inputfile> > <outputfile>
这不能满足删除上一行的要求,但是您的示例似乎不需要该功能。