web-dev-qa-db-ja.com

マッチの前後にN番目とM番目の行を返すgrep

Grepを使用すると、フィールド-Aおよび-Bを使用して、一致から前の行と次の行を取得できることを知っています。

ただし、多くの行が指定されていることに基づいて、マッチ間のすべての行を取り込みます。

grep -r -i -B 5 -A 5 "match" 

5のみを受け取りたい番目 一致する前の行と5番目 一致した行に加えて一致した後の行で、その間の行を取得しません。

grepでこれを行う方法はありますか?

10
chollida

使用するツールは、シフトと呼ばれます。これは基本的にステロイドのgrepです。並行してGrep。ふるいには、あなたが望むことを正確に行うための膨大な量のオプションがあります-具体的には、/テキストの後に続く/ない可能性のあるマッチに関連する特定の行を返します。

Siftはgo言語で書かれているので主流のgnuではなく、Linuxに問題なくインストールできることに驚かされます。 ITは、すべてのCPUの膨大な量のテキストを使用して並行して検索しますが、grepは同じことをするのに数週間かかります。

ウェブサイトをシフト-例参照

1

次の場合:

cat file
a
b
c
d
e
f match
g
h
i match
j
k
l
m
n
o

次に:

awk '
    {line[NR] = $0} 
    /match/ {matched[NR]} 
    END {
        for (nr in matched)
            for (n=nr-5; n<=nr+5; n+=5) 
                print line[n]
    }
' file
a
f match
k
d
i match
n
12
glenn jackman

これは基本的にグレンのソリューションですが、Bash、Grep、およびsedで実装されています。

grep -n match file |
    while IFS=: read nr _; do
        sed -ns "$((nr-5))p; $((nr))p; $((nr+5))p" file
    done

行番号が1未満の場合はsedエラーが発生し、ファイル内の行数より大きい行番号の場合は何も印刷されないことに注意してください。

これは最低限のものです。再帰的に動作させ、上記の行番号のケースを処理するには、ある程度の作業が必要です。

6
wjandrea

grepだけではできません。 edがオプションの場合:

ed -s file << 'EOF' 
g/match/-5p\
+5p\
+5p
EOF  

スクリプトは基本的に、/ match /が一致するたびに、その5行前に行を印刷し、その後に5行、その後に5行を印刷します。

6
JoL
awk '/match/{system("sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME)}' infile

ここでは、awksystem(command)関数を使用して外部を呼び出していますsedawkが5のパターンmatchと一致した行を印刷するコマンド番目 試合の前後の行。

構文は簡単です。外部コマンド自体をスイッチと同様に二重引用符で囲み、コマンドに正確に渡すものをエスケープする必要があります。awkオプション自体に関連する他のすべては引用符の外側にある必要があります。したがって、以下sed

"sed -n \"" NR-5 "p;" NR "p;" NR+5 "p\" " FILENAME

に翻訳する:

sed -n "NR-5p; NRp; NR+5p" FILENAME

NR はパターンmatchと一致した行番号であり、 FILENAME は現在の処理のfilenameawkで渡す。

5
αғsнιη

@glennのサンプルテキストファイルを使用し、awkの代わりにPerlを使用します。

$ Perl -n0E 'say /(.*\n)(?=(?:.*\n){4}(.*match.*\n)(?:.*\n){4}(.*\n))/g' ex

同じ結果が得られますが、実行速度は速くなります。

a
f match
k
d
i match
n
2
user216043