2009-11-06 58 views
4

通常使用grep命令来显示包含指定模式的行。有什么方法可以在包含指定模式的行之前和之后显示n行?高级grep unix

这可以通过awk来实现吗?

+0

http://betterthangrep.com/ – Artelius 2009-11-06 05:57:48

+1

Dup的:http://stackoverflow.com/questions/9081/grep-a-file-but-show-several-surrounding-行 – paxdiablo 2009-11-06 06:01:35

+0

@Artelius,我不能依靠其他软件。 – 2009-11-06 06:07:57

回答

7

是,使用

grep -B num1 -A num2 

到包括在比赛前上下文的NUM1线,并且在比赛后上下文NUM2线。

编辑:

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

this link描述了AIX 4.3的grep(不看好

马特的perl脚本可能是一个更好的解决方案。

+0

它不能在我的systrm上运行 grep -B 3 -A 2 sunny sachin grep:非法选项-B B 用法:grep -hblcnsviw模式文件。 。 。 – 2009-11-06 06:05:35

+0

我正在AIX上工作。 – 2009-11-06 06:13:04

+0

我已经重申了这个问题。我希望AIX专家出现。 – pavium 2009-11-06 06:16:20

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. 
+0

它不适用于AIX,我的歉意还没有提到,这个问题在AIX上。 – 2009-11-06 06:30:09

+0

检查我的其他答案,它应该适用于AIX,因为AIX支持-n参数。 – Puppe 2009-11-06 06:36:36

+0

我们可以为这个 – 2009-11-06 06:41:45

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线(也就是你匹配的行加上前行后的数量)

+0

这是最接近GNU grep -A-B-C输出的版本(除了不输出组分隔符( - ))。 – Bruce 2017-11-24 11:21:46

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 
+0

是的,我试过,但它不会工作,出现错误 awk:第1行附近的语法错误 awk:在第1行附近跳出 – 2009-11-17 05:28:17

+0

如果有,请使用nawk。 – ghostdog74 2009-11-17 06:07:07

3

这是我平时做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 varialble就是你可以随时使用它的一个行:

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

假设我有一个模式“堆”和文件名是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 & grep。从上面的模式'堆'与文件名是流。* - 前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.* 
+0

当我想要匹配更多像flow这样的文件时,我应该如何重写它。* – hudi 2015-08-25 08:16:56

+0

您可以用flow。*替换flow.txt,其中2个位置用于grep,一个用于awk。例如 - 对于模式“堆栈”,文件名是流。* - 前2行和后3行。该命令将如下所示:'grep -n'stack'flow。* | cut -d':'-f1 | xargs -n1 -I%awk'NR <=%+3 && NR> =% - 2'flow。*' – 2015-08-25 17:19:37

+0

为了清晰起见,更新了上面的文章。 – 2015-08-25 17:25:24