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


12

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

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

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

私は5を受け取りたい番目の試合前のラインと5 番目のマッチラインに加えて、試合後の行をとの間に線を取得できません。

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


1
それをsedにパイプすることでできます。私はこれをテストしただけで機能しましたが、ファイルに1つの完全一致があった場合にのみ機能し grep -r -i -B 5 -A 5 "match" | sed -e 1b -e '$!d'
Terrance

@Terranceは、あなたが言うように提案をありがとう、私はこれが機能しない1000の行を収集しているので。
チョリダ

私はgrepが単独で動作するとは思わない...私はあなたのためのbashスクリプトに取り組んでいます
ジョシュア・ベスネッテ

問題ない!どんな答えが得られるのか興味があります。=)
テランス

これは1つのファイルですか、それとも複数のファイルですか?
ジョシュアベスネッテ

回答:


1

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

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

ウェブサイトをふるいにかける-例を参照


AskUbuntuへようこそ、回答ありがとうございます。Webサイトへのリンクを提供するのではなく、この特定の問題を解決できるCLIの例を提供する必要があります。これは結局Q&Aです、ありがとう。
バーナードウェイ

12

次の場合:

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

+1、しかし、セマンティクスを説明してもらえます/match/ {matched[NR]}か?コマンド全体として配列や変数を見たことはありません。一致した各行の現在のレコード番号を配列に入れていますか?
ジョー

これは奇妙なことです:割り当てなしで配列要素を参照すると、そのキーが配列に追加されます(値なし)。次に、そのキーが式に表示されますkey in array。私がやっていることは、パターンが表示される行番号を覚えていることです
グレンジャックマン

6

これは基本的にグレンのソリューションですが、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

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

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

スクリプトは基本的に、/ match /のすべての一致に対して、その5行前、次に5行、そしてその後5行を印刷します。


5
@ubashu OPが単純なフラット「grepではできません」を与えると、より役立つと思いますか?OPの問題を解決するための優れた代替手段となるものを提供しています。ヘルプセンターから:「質問は具体的に何を求めているのですか?あなたの答えがそれを提供することを確認してください-または実行可能な代替案。答えは「それをしない」であることができます。 」
JoL


5
@ubashu grep答えではありませんが、「Xではできないが、Yでできる」という答えは、OPの質問に答えるだけでなく、代替手段も提供するため、依然として有効な答えです。それはうまくいくでしょう。これは、ここでの有効なタイプの回答です。
トーマス区

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

ここでは、awkの関数を使用して外部コマンドを呼び出し、awkがpattern と一致した行を、一致の前後の5 行で出力します。system(command)sedmatch

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

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

に翻訳する:

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

NRは、パターンmatchと一致した行番号でFILENAMEあり、を通過する現在の処理ファイル名awkです。


2

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

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

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

a
f match
k
d
i match
n

ジョアンは、あなたはLQのレビューキューと@waltinatorを削除する投票で、その次の時間があることまで見せているほんの少しより冗長な... ;-) また+1をLQキューのあなたを得るために... :P
ファビー

1
@JJoao低品質のレビューキュー。90%のコードだったので、おそらくあなたの答えはそこで拾われました。
-wjandrea

1
@JJoao 90%という数字は、私の説明の仕方です。実際にどのヒューリスティックが使用されているのかわかりません。
wjandrea

1
メノスカフェ、メインエスクリタ!@JJoao :D ;-):D
Fabby

1
@Fabby:Semcafénada funciona:D-おそらくLCQに表示されます(=ローコーヒーキュー)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.