通常 grep 命令用于显示包含指定模式的行。有没有办法在包含指定模式的行之前和之后显示 n 行?
这可以使用awk来实现吗?
是的,使用
grep -B num1 -A num2
包括匹配前的 num1 行上下文,以及匹配后的 num2 行上下文。
编辑:
似乎OP正在使用AIX。这有一组不同的选项,不包括 -B 和 -A
此链接描述了 AIX 4.3 上的 grep(看起来不太有希望)
Matt 的 perl 脚本可能是一个更好的解决方案。
以下是我通常在 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>
假设我有一个模式“堆栈”并且文件名是 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。从上面看,文件名为flow.*的模式 'stack' - 前 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.*
从标签来看,系统可能有一个不支持提供上下文的 grep(Solaris 是一个不支持提供上下文的系统,我不记得 AIX)。如果是这种情况,在http://www.sun.com/bigadmin/jsp/descFile.jsp?url=descAll/cgrep__context_grep有一个 perl 脚本可能会有所帮助。
如果你有 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 行(即,您的匹配行加上之前和之后的行数)
你可以使用 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
当然有(来自 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.