搜索并删除与模式匹配的行以及前一行的注释(如果有)

搜索并删除与模式匹配的行以及前一行的注释(如果有)

我需要在 csh 中编写一个 shell 脚本来搜索和删除与模式匹配的行以及前一行的注释(如果有)。例如,如果我的文件有以下几行

Shell 脚本
#这是一个测试
模式1
格式1
模式2
格式2
#格式3
模式3

如果搜索模式是“pattern”,则输出应如下所示

Shell 脚本
格式1
格式2

更准确地说,应该删除包含模式的行以及以“#”开头的上一行

谢谢您的帮助

答案1

首先任何人都不应该使用csh对于任何事来说,它都过时了,而且功能不够强大(不是“不足”)。其次,我怀疑它能否胜任这项任务。第三,更有可能的是awksed甚至 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/);

基本上,循环是上一行后面的一行。它表示可以打印上一行如果:

  1. 如果当前行与模式匹配:只要前一行也不与模式匹配,或者是注释,就可以打印前一行。
  2. 如果这一行不是模式,那么只要它与模式不匹配,就可以打印前一行。

您可以将代码保存在文件中并按如下方式使用它:perl thefile.pl textfile_you_want_to_filter

答案4

它必须是 shell 脚本吗?

  1. 使用 vi 打开文件
  2. :g/<pattern>/d
  3. 根据需要重复添加其他模式类型,除非你可以用正则表达式表达模式
  4. :g/^#/d

如果必须编写脚本,可以使用 sed 有效地重现

编辑:

1.创建文件.sedscript:

/pattern/d
/^#/d

2.sed -f .sedscript <inputfile> > <outputfile>

这不能满足删除上一行的要求,但是您的示例似乎不需要该功能。

相关内容