試合前後のグレップ文字?


144

これを使用する:

grep -A1 -B1 "test_pattern" file

ファイル内の一致したパターンの前後に1行を生成します。行ではなく指定した数の文字を表示する方法はありますか?

私のファイルの行はかなり大きいので、行全体を印刷するのではなく、コンテキストで一致を観察するだけです。これを行う方法に関する提案はありますか?


回答:


184

前3文字、後4文字

$> echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}'
23_string_and

5
少量のデータには適切な回答ですが、100文字を超える文字を一致させると遅くなります。たとえば、巨大なxmlファイルで、前後に{1,200}が必要ですが、使用するには遅すぎます。
Benubird 2013年

3
@amit_gによるawkバージョンははるかに高速です。
ssobczak 14

6
Mac OSXでは利用できないため、これは広く利用可能なソリューションではありません。-Eバージョン(以下にリスト)は、より優れたソリューションです。-Pとは何ですか?続きを読む... -P、--perl-regexp PATTERNをPerl正規表現として解釈します(PCRE、以下を参照)。これは非常に実験的なものであり、grep -Pは実装されていない機能を警告する場合があります。
Xofo 2014年

2
OSXでインストール:brew install homebrew/dupes/grepとして実行しますggrep
kenorb

1
@Benubirdが暗示するように、これは、マッチターゲットに必要な適度に広い周囲を持つ巨大なファイルに使用することはパフォーマンス的に不可能です。
Matanster

113
grep -E -o ".{0,5}test_pattern.{0,5}" test.txt 

これは、パターンの前後5文字までに一致します。-oスイッチは、grepに一致のみを表示し、-Eは拡張正規表現を使用するように指示します。式を引用符で囲んでください。そうしないと、シェルによって解釈される可能性があります。


1
ので、それは{}で長さ2 ^ 8-1で蓋をしていますことを良い答え、面白い{0,255}作品が{0,256}できますgrep: invalid repetition count(s)
CodeMonkey

一致する文字の数(5-> 25-> 50)を増やすと、パフォーマンスが大幅に低下するようですが、なぜですか?
アダムヒューズ

37

あなたは使うことができます

awk '/test_pattern/ {
    match($0, /test_pattern/); print substr($0, RSTART - 10, RLENGTH + 20);
}' file

2
少し大きいファイルでもうまく機能します
Touko

4
これを使用して、行ごとに複数の一致を見つけるにはどうすればよいですか?
koox00

1
中括弧で囲まれたペアの最初の数字の意味は何ですか?"grep -E -o"。{0,5} test_pattern。{0,5} "test.txt"の0のように?
ルーロックウェルファン2017

本当に高速ですが、@ ekseの回答ほど正確ではありません。
アブドラ

24

つまり、このように:

grep -o '.\{0,20\}test_pattern.\{0,20\}' file

これにより、の両側に最大20文字が印刷されますtest_pattern\{0,20\}表記法は次のようである*が、指定は20回の繰り返しの代わりにゼロにゼロまたはmore.Theは-oむしろ全体のラインよりも、唯一の試合自体を表示するように言います。


このコマンドは私には機能しません:grep: Invalid content of \{\}
Alexander Pravdin

0

ではgawk、一致関数を使用できます。

    x="hey there how are you"
    echo "$x" |awk --re-interval '{match($0,/(.{4})how(.{4})/,a);print a[1],a[2]}'
    ere   are

でよろしければperl、より柔軟な解決策:パターンの前に3文字、実際のパターン、パターンの後の5文字の順に印刷します。

echo hey there how are you |perl -lne 'print "$1$2$3" if /(.{3})(there)(.{5})/'
ey there how

これは、文字だけでなく単語にも適用できます。以下は、実際に一致する文字列の前に1つの単語を出力します。

echo hey there how are you |perl -lne 'print $1 if /(\w+) there/'
hey

以下は、パターンの後に1つの単語を出力します。

echo hey there how are you |perl -lne 'print $2 if /(\w+) there (\w+)/'
how

以下は、パターンの前に1つの単語を出力し、次に実際の単語、次にパターンの後に1つの単語を出力します。

echo hey there how are you |perl -lne 'print "$1$2$3" if /(\w+)( there )(\w+)/'
hey there how

0

あなたは見つけるために正規表現のgrepを使用することができます+ハイライトのために2番目のgrep

echo "some123_string_and_another" | grep -o -P '.{0,3}string.{0,4}' | grep string

23_string_and

ここに画像の説明を入力してください


0

これらの不可解なコマンド修飾子を簡単に覚えることは決してないので、私はトップの回答を取り、それを~/.bashrcファイル内の関数に変換しました。


cgrep() {
    # For files that are arrays 10's of thousands of characters print.
    # Use cpgrep to print 30 characters before and after search patttern.
    if [ $# -eq 2 ] ; then
        # Format was 'cgrep "search string" /path/to/filename'
        grep -o -P ".{0,30}$1.{0,30}" "$2"
    else
        # Format was 'cat /path/to/filename | cgrep "search string"
        grep -o -P ".{0,30}$1.{0,30}"
    fi
} # cgrep()

実際の動作は次のとおりです。

$ ll /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

-rw-r--r-- 1 rick rick 25780 Jul  3 19:05 /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

$ cat /tmp/rick/scp.Mf7UdS/Mf7UdS.Source | cgrep "Link to iconic"

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

$ cgrep "Link to iconic" /tmp/rick/scp.Mf7UdS/Mf7UdS.Source

1:43:30.3540244000 /mnt/e/bin/Link to iconic S -rwxrwxrwx 777 rick 1000 ri

問題のファイルは1つの連続した25K行であり、regularを使用して探しているものを見つけることはできませんgrep

cgrepそのparallels grepメソッドを呼び出すことができる2つの異なる方法に注意してください。

「$ 2」が設定されている場合にのみ渡される関数を作成する「より洗練された」方法があり、4行のコードを節約します。私はそれを便利に持っていません。のようなもの${parm2} $parm2。見つかった場合は、関数とこの回答を修正します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.