通常、指定したパターンを含む行を表示するには、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 つの変数が必要ない場合は、いつでも 1 行で使用できます。
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 用に変更します。上記のパターン「stack」のファイル名は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.*
タグから、コンテキストの提供をサポートしていない可能性のある grep がシステムにある可能性があります (Solaris はサポートしていないシステムの 1 つであり、AIX については思い出せません)。その場合は、http://www.sun.com/bigadmin/jsp/descFile.jsp?url=descAll/cgrep__context_grep に役立つ perl スクリプトがあります。
sed がある場合は、このシェルスクリプトを使用できます
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のmanページから):
-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.
あなたは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