行の長さが数千文字を超えるJSONファイルをgrepする必要があります。 一致の左側と右側に最大N文字のコンテキストを表示するようにgrepを制限するにはどうすればよいですか?一般的なLinuxパッケージで使用できる限り、grep以外のツールでも問題ありません。
これは想像上のgrepスイッチФの出力例です:
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -Ф 10 -r foo *
hello.txt: ime a big foo came of t
GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
説明:
-o
=>一致したもののみを印刷-P
=> Perlスタイルの正規表現を使用$N
文字の後にfoo
が続き、その後に0〜$N
文字が続くと言います。GNU grep
がない場合:
find . -type f -exec \
Perl -nle '
BEGIN{$N=10}
print if s/^.*?(.{0,$N}foo.{0,$N}).*?$/$ARGV:$1/
' {} \;
説明:
grep
がGNU grep
であることに依存できなくなったため、find
を利用してファイルを再帰的に検索します(-r
action of GNU grep
)。見つかったファイルごとに、Perlスニペットを実行します。
Perlスイッチ:
-n
ファイルを1行ずつ読み取ります-l
各行の末尾の改行を削除して、印刷時に元に戻します-e
次の文字列をコードとして扱いますPerlスニペットは基本的にgrep
と同じことをしています。まず、変数$N
を必要なコンテキスト文字の数に設定します。 BEGIN{}
は、これがすべてのファイルのすべての行に対して1回ではなく、実行の開始時に1回だけ実行されることを意味します。
各行に対して実行されるステートメントは、正規表現の置換が機能する場合に行を出力することです。
正規表現:
^.*?
)の後にgrep
の場合と同様に.{0,$N}
が続き、その後にfoo
後に別の.{0,$N}
が続き、最後に古い行の終わりまで遅延すること(.*?$
)。$ARGV:$1
に置き換えます。 $ARGV
は、読み込まれている現在のファイルの名前を保持する魔法の変数です。 $1
は、括弧が一致したものです。この場合のコンテキストです。foo
の前にすべての文字を消費するため、一致に失敗することはないため(.{0,$N}
は0回一致できるため)、両端での遅延一致が必要です。1つまり、全体的な一致が失敗しない限り、何も一致させないことをお勧めします。つまり、できるだけ少ない文字数で一致させます。
これを使ってみてください:
grep -r -E -o ".{0,10}wantedText.{0,10}" *
-Eは、拡張正規表現を使用することを示します
-oは、一致のみを印刷することを示します
-r grepはフォルダ内で再帰的に結果を探しています
正規表現:
{0,10}は、印刷する任意の文字数を示します
。は任意の文字を表します(ここでは文字自体は重要ではなく、番号のみが重要でした)
編集:ああ、なるほど、ジョセフは私と同じソリューションを推奨している:D
-b
フラグを使用してstdoutをcut
にパイプします。grepの出力に1行あたり1〜400バイトだけを指示できます。
grep "foobar" * | cut -b 1-400
以下から取得: http://www.topbug.net/blog/2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ および https://stackoverflow.com/a/39029954/1150462
推奨されるアプローチ".{0,10}<original pattern>.{0,10}"
は、ハイライトの色がしばしばめちゃくちゃになることを除いて、完全に良いです。同様の出力でスクリプトを作成しましたが、色も保持されています。
#!/bin/bash
# Usage:
# grepl PATTERN [FILE]
# how many characters around the searching keyword should be shown?
context_length=10
# What is the length of the control character for the color before and after the matching string?
# This is mostly determined by the environmental variable GREP_COLORS.
control_length_before=$(($(echo a | grep --color=always a | cut -d a -f '1' | wc -c)-1))
control_length_after=$(($(echo a | grep --color=always a | cut -d a -f '2' | wc -c)-1))
grep -E --color=always "$1" $2 | grep --color=none -oE ".{0,$(($control_length_before + $context_length))}$1.{0,$(($control_length_after + $context_length))}"
スクリプトがgrepl
として保存されているとすると、grepl pattern file_with_long_lines
は、一致する行を表示しますが、一致する文字列の前後に10文字しかありません。