在不同的grep关键字上显示不同的上下文

时间:2012-12-19 04:23:28

标签: bash search grep

我知道-A -B -C可用于显示grep关键字周围的上下文。

我的问题是,如何在不同的关键字上显示不同的背景信息?

例如,如何为cat显示-A 5,为狗显示-B 4,为猴子显示-C 1

egrep -A3 "cat|dog|monkey" <file> 
// this just show 3 after lines for each keyword. 

3 个答案:

答案 0 :(得分:1)

我担心grep不会这样做。你必须使用不同的工具。也许写自己的程序。

答案 1 :(得分:1)

我认为没有任何方法可以通过单个grep调用来完成它,但你可以通过grep为每个变量运行一次并连接输出:

var=$(grep -n -A 5 cat file)$'\n'$(grep -n -B 4 dog file)$'\n'$(grep -n -C 1 monkey file)
var=$(sort -un <(echo "$var"))

现在echo "$var"将产生与单个命令相同的输出,加上行号和上下文指示符(:前缀表示与模式完全匹配的行,以及{ {1}}前缀表示由于- -A和/或-B选项而包含的行。

到目前为止我包含行号的原因是为了保留您在一个语句中设法执行此操作时所看到的结果的顺序。如果你喜欢它们,那很好,但如果不喜欢,你可以使用以下行来删除它们:

-C

这会传递一次以剪切精确匹配线的前缀,然后再次切割上下文匹配的前缀。

漂亮?没有。但它确实有效。

答案 2 :(得分:0)

这样的事情可以做到:

awk '
   BEGIN{ ARGV[ARGC++] = ARGV[1] }

   function prtB(nr) { for (i=FNR-nr; i<FNR;     i++) print a[i] }
   function prtA(nr) { for (i=FNR+1;  i<=FNR+nr; i++) print a[i] }

   NR==FNR{ a[NR]; next }

   /cat/    { print; prtA(5) }
   /dog/    { prtB(4); print }
   /monkey/ { prtB(1); print; prtA(1) }

' file

检查函数中循环的数学运算。例如,您没有说明如何处理包含猴子和狗的行。

编辑:这是一个未经测试的解决方案,可以在任何匹配项周围打印最大上下文,让您在命令行中指定上下文,并且不会使用与上述廉价而愉快的解决方案一样多的内存:

awk -v cxts="cat:0:5\ndog:4:0\nmonkey:1:1" '
   BEGIN{
      ARGV[ARGC++] = ARGV[1]
      numCxts = split(cxts,cxtsA,RS)
      for (i=1;i<=numCxts;i++) {
         regex = cxtsA[i]
         n = split(regex,rangeA,/:/)
         sub(/:[^:]+:[^:]+$/,"",regex)
         endA[regex]   = rangeA[n]
         startA[regex] = rangeA[n-1]
         regexA[regex]
      }
   }

   NR==FNR{
      for (regex in regexA) {
         if ($0 ~ regex) {
            start = NR - startA[regex]
            end   = NR + endA[regex]
            for (i=start; i<=end; i++) {
               prt[i]
            }
         }
      }
      next
   }

   FNR in prt

' file

将搜索到的cxts变量中的模式与您的RS值分开,默认为换行符。