grep 的 -A -B -C 开关是否有任何替代方案(在 之前和之后打印几行)?

grep 的 -A -B -C 开关是否有任何替代方案(在 之前和之后打印几行)?
grep -A 2 -B 3 

在 grep 字符串之后打印 2 行,并在之前打印 3 行。

grep -C 3

打印前 3 行和后 3 行

不幸的是,grep我正在使用的不支持这些选项。是否有任何替代命令或脚本可用于模拟此操作?使用sed/// shell脚本awkperl

答案1

一种相当丑陋的方法是

grep -v pattern file >file.tmp; diff -c file.tmp file

或者用 替换-c上下文-C NUMNUM。不过,它会产生额外的输出。(如果你diff支持-u/ -U NUM,它会更干净。)

如果你diff没有-c// -C-u仍然有办法做到这一点,但它们非常丑陋。另一方面,一个diff不支持 Perl的系统-c可能也没有 Perl。

答案2

确认仅需要 Perl,并且包括-A-B-C与 grep 类似的选项。它使用 Perl 的正则表达式语法而不是 grep 的语法,并且选择要搜索的文件的方式也完全不同。您可能想-f在使用它时尝试该选项(打印出它将搜索的文件,而不实际搜索任何内容)。

它可以安装为单个脚本不需要非核心模块。只需将其放入您的~/bin目录(或 PATH 上您有写入权限的任何其他位置)并确保它是chmod可执行的。

答案3

这个简单的 perl 脚本grep -A在某种程度上模拟

#!/usr/bin/perl

$pattern=shift; #patthern to search
$lines=shift; # number of lines to print

$n = 0;
while (<>) {
  $n = $lines if /$pattern/; # reset counting
  if ($n) { print; $n-- } # print if within
  $n = 0 if eof; # don't leak across file boundaries
}

请注意,您可以添加使用语句,以使脚本可读且可用;)

USAGE:    $./grep-A.pl <pattern> <numLines> <filename> 

答案4

事实证明,模拟 -B 相当棘手,因为当匹配行直接相互跟随时会出现问题。这几乎不允许使用任何类型的单通道文件扫描。

我在尝试以下近似值时意识到了这一点:

perl -pe 'if(/search_term/) {print foreach @A; print ">"; $B=4}; shift @A if push(@A, $_)>7; $_ = "" unless ($B-- > 0);' target_file

这将大致正确地与 grep -A7 -B3 一样,并带有第一段中描述的警告。

此问题的另一种(也是单文件)解决方案是使用 perl 向 sed 提供命令字符串:

sed -n `perl -pe '$_=(/search_term/?sprintf("%d,%dp;", $.-3,$.+4):"")' file` file

相关内容