高级grep unix

时间:2009-11-06 05:53:32

标签: unix aix

通常grep命令用于显示指定模式的行。有没有办法在包含指定模式的行之前和之后显示n行?

这可以用awk实现吗?

6 个答案:

答案 0 :(得分:7)

是的,使用

grep -B num1 -A num2 

在匹配前包含num1行上下文,在匹配后包含num2行上下文。

编辑:

似乎OP正在使用AIX。这有一组不同的选项,不包括-B和-A

this link描述了AIX 4.3上的grep(它看起来并不乐观

Matt的perl脚本可能是更好的解决方案。

答案 1 :(得分:4)

这是我在AIX上通常做的事情:

before=2  << The number of lines to be shown Before >>
after=2   << The number of lines to be shown After >>
grep -n <pattern> <filename> | cut -d':' -f1 |  xargs  -n1 -I % awk "NR<=%+$after && NR>=%-$before" <filename>

如果您不想要额外的2个变量,您可以随时使用它一行:

grep -n <pattern> <filename> | cut -d':' -f1 |  xargs  -n1 -I % awk 'NR<=%+<<after>> && NR>=%-<<before>>' <filename>

假设我有一个模式'stack',文件名是flow.txt 我想要之前的2行和之后的3行。该命令将如下:

grep -n 'stack' flow.txt | cut -d':' -f1 |  xargs  -n1 -I % awk 'NR<=%+3 && NR>=%-2' flow.txt

我之前只想要2行 - 命令就像:

grep -n 'stack' flow.txt | cut -d':' -f1 |  xargs  -n1 -I % awk 'NR<=% && NR>=%-2' flow.txt

我只想要3行 - 命令就像:

grep -n 'stack' flow.txt | cut -d':' -f1 |  xargs  -n1 -I % awk 'NR<=%+3 && NR>=%' flow.txt

多个文件 - 将其更改为Awk&amp; grep的。从上面看,带有文件名的模式“堆栈”是 flow。* - 前面有2行,后面有3行。该命令将如下:

    awk 'BEGIN { 
    before=1; after=3; pattern="stack";
    i=0; hold[before]=""; afterprints=0}
    { 
    #Print the lines from the previous Match
    if (afterprints > 0)
      {
      print FILENAME ":" FNR ":" $0
      afterprints-- #keep a track of the lines to print after - this can be reset if a match is found
      if (afterprints == 0) print "---"
      }
    #Look for the pattern in current line
    if ( match($0, pattern) > 0 )
      {
      # print the lines in the hold round robin buffer from the current line to line-1
      #  if (before >0)  => user wants lines before avoid divide by 0 in %
      #  and afterprints => 0 - we have not printed the line already
      for(j=i; j < i+before && before > 0 && afterprints == 0 ; j++)
        print hold[j%before]
      if (afterprints == 0) #  print the line if we have not printed the line already
        print FILENAME ":" FNR ":" $0
      afterprints=after
      }
    if (before > 0) # Store the lines in the round robin hold buffer
      { hold[i]=FILENAME ":" FNR ":" $0
        i=(i+1)%before }
  }' flow.*

答案 2 :(得分:1)

从标签中,系统可能有一个可能不支持提供上下文的grep(Solaris是一个没有,我不记得有关AIX的系统)。如果是这种情况,那么perl脚本可能会对http://www.sun.com/bigadmin/jsp/descFile.jsp?url=descAll/cgrep__context_grep提供帮助。

答案 3 :(得分:1)

如果你有sed,你可以使用这个shell脚本

BEFORE=2
AFTER=3
FILE=file.txt
PATTERN=pattern
for i in $(grep -n $PATTERN $FILE | sed -e 's/\:.*//')
  do head -n $(($AFTER+$i)) $FILE | tail -n $(($AFTER+$BEFORE+1))
done

它的作用是,grep -n前缀每个匹配它找到的行,sed除了找到它之外的所有行。然后你使用head将线条放到它找到的线上加上另外的$ AFTER线。然后将它传送到尾部以获得$ BEFORE + $ AFTER + 1行(即,您的匹配行加上前后行数)

答案 4 :(得分:0)

当然有(来自grep手册页):

   -B NUM, --before-context=NUM
          Print  NUM  lines  of  leading  context  before  matching lines.
          Places  a  line  containing  a  group  separator  (--)   between
          contiguous  groups  of  matches.  With the -o or --only-matching
          option, this has no effect and a warning is given.

   -A NUM, --after-context=NUM
          Print NUM  lines  of  trailing  context  after  matching  lines.
          Places   a  line  containing  a  group  separator  (--)  between
          contiguous groups of matches.  With the  -o  or  --only-matching
          option, this has no effect and a warning is given.

如果你想在匹配之前和之后获得相同数量的行,请使用:

   -C NUM, -NUM, --context=NUM
          Print NUM lines of output context.  Places a line  containing  a
          group separator (--) between contiguous groups of matches.  With
          the -o or --only-matching option,  this  has  no  effect  and  a
          warning is given.

答案 5 :(得分:0)

你可以使用awk

awk 'BEGIN{t=4}
c--&&c>=0
/pattern/{ c=t; for(i=NR;i<NR+t;i++)print a[i%t] }
{ a[NR%t]=$0}
' file

输出

$ more file
1
2
3
4
5
pattern
6
7
8
9
10
11

$ ./shell.sh
2
3
4
5
6
7
8
9