1

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

我的问题是,如何在不同的关键字上显示不同的上下文?

例如,我如何-A 5为猫、-B 4狗和-C 1猴子显示:

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

3 回答 3

2

我认为没有任何方法可以通过单个 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"))

nowecho "$var"将产生与您从单个命令中获得的相同的输出,加上行号和上下文指示符(:前缀表示与模式完全匹配的行,-前缀表示由于-A -Band/or-C选项而包含的行) .

到目前为止,我包含行号的原因是为了保留如果您设法在一个语句中做到这一点,您会看到的结果的顺序。如果您喜欢它们,很好,但如果不喜欢,您可以使用以下行将它们删掉:

var=$(cut -d: -f2- <(echo "$var") | cut -d- -f2-)

这将通过一次以剪切精确匹配行的前缀,然后再次剪切上下文匹配的前缀。

漂亮的?不。但它有效。

于 2012-12-19T14:58:40.037 回答
1

恐怕grep不会那样做。您将不得不使用不同的工具。也许编写自己的程序。

于 2012-12-19T04:53:38.063 回答
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 值分开,默认为换行符。

于 2012-12-19T15:39:57.267 回答