Advanced grep unix
通常grep命令用于显示指定模式的行。 有没有办法在包含指定模式的行之前和之后显示n行?
这可以用awk实现吗?
是的,使用
1 | grep -B num1 -A num2 |
在匹配之前包含num1行上下文,在匹配之后包含num2行上下文。
编辑:
似乎OP正在使用AIX。这有一组不同的选项,不包括-B和-A
此链接描述了AIX 4.3上的grep(它看起来并不乐观)
Matt的perl脚本可能是更好的解决方案。
这是我在AIX上通常做的事情:
1 2 3 | 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个变量,你总是可以使用它一行:
1 | grep -n <pattern> <filename> | cut -d':' -f1 | xargs -n1 -I % awk 'NR<=%+<> && NR>=%-<<before>>' <filename> |
假设我有一个模式'stack',文件名是flow.txt
我想要之前的2行和之后的3行。该命令将如下:
1 | grep -n 'stack' flow.txt | cut -d':' -f1 | xargs -n1 -I % awk 'NR<=%+3 && NR>=%-2' flow.txt |
我之前只想要2行 - 命令就像:
1 | grep -n 'stack' flow.txt | cut -d':' -f1 | xargs -n1 -I % awk 'NR<=% && NR>=%-2' flow.txt |
我只想要3行 - 命令就像:
1 | grep -n 'stack' flow.txt | cut -d':' -f1 | xargs -n1 -I % awk 'NR<=%+3 && NR>=%' flow.txt |
多个文件 - 为Awk&amp;更改它grep的。从上面看,带有文件名的模式'stack'是flow。* - 前面有2行,后面有3行。该命令将如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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.* |
如果你有sed,你可以使用这个shell脚本
1 2 3 4 5 6 7 | 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行(即,您的匹配行加上前后的行数)
从标签中,可能是系统有一个可能不支持提供上下文的grep(Solaris是一个没有,我不记得有关AIX的系统)。如果是这种情况,那么可以在http://www.sun.com/bigadmin/jsp/descFile.jsp?url=descAll/cgrep__context_grep上找到一个可能有用的perl脚本。
你可以使用awk
1 2 3 4 5 | 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 |
产量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | $ more file 1 2 3 4 5 pattern 6 7 8 9 10 11 $ ./shell.sh 2 3 4 5 6 7 8 9 |
当然有(从grep手册页):
1 2 3 4 5 6 7 8 9 10 11 | -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. |
如果你想在匹配之前和之后获得相同数量的行,请使用:
1 2 3 4 5 | -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. |