文字列を含む行を見つけて特定の行やその他の内容を印刷する方法

文字列を含む行を見つけて特定の行やその他の内容を印刷する方法

次のコマンドを使用して複数のファイルを再帰的に検索し、各ファイルで文字列が見つかった行番号を見つけました。

    grep -nr "the_string" /media/slowly/DATA/lots_of_files > output.txt

出力は次のとおりです。

    /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt:3:the_string
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:6:the_string is in this sentence.
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:9:the_string is in this sentence too.

上記のように、出力にはファイル名、行番号、および行のすべてのテキスト(文字列を含む)が含まれます。

また、以下を使用して、文字列を含むファイルの特定の行のみを印刷する方法もわかりました。

    sed '3!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt > print.txt
    sed '6!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt
    sed '9!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt

行番号とファイル名を読み、手動で上記のコマンドを生成しました。

これが私の問題です。

Q1a

これらの2つのステップを1つのコマンドにまとめる方法はありますか?行番号とファイル名をsedに関連付け、その行を印刷しようとしています。 grep出力が生成される順序に関する質問があります。

第1四半期

上記と同じですが、文字列を含む行の前後2行を印刷します(合計5行)?私は行番号とファイル名をsedに関連付けて、必要なすべての行を何とか印刷するつもりです。

とても感謝しています。

答え1

質問を正しく理解したら、grepコマンドを使用してこれを実行できます。

Q1aの場合、grep出力で抑制されたファイル名を使用できます-h。たとえば、次のようになります。

grep -hnr "the_string" /media/slowly/DATA/lots_of_files > output.txt

Q1bの場合、出力grepには使用と一致する行の前後に行を含めることができます-A-Bたとえば、次のようになります。

grep -hnr -A2 -B2 "the_string" /media/slowly/DATA/lots_of_files > output.txt

出力には一致の間に区切り文字が含まれており、それを使用して表示しないことがあります--no-group-separator。たとえば、次のようになります。

grep -hnr -A2 -B2 --no-group-separator "the_string" /media/slowly/DATA/lots_of_files > output.txt

出力は、一致行(:)とコンテキスト行(-)に異なる区切り文字を使用します。

答え2

私の知る限り、あなたの最初の質問はgrepさまざまな方法で答えることができます。ファイルリスト(または-rで使用または再帰するディレクトリ)を送信すると、行-R番号と一致するものが見つかったファイルが常に出力されます。この問題を解決するには、次の構成を使用できます。

find /path/to/files -type f | xargs grep -n 'the_pattern'

2番目の質問の場合、ゲームの前後の行を表示するには、次のものを使用できます-Cコンテキスト)スイッチ:

grep -C2 'pattern' /path/to/file # displays the two lines before and after a match

関連-C-A以降)と-B第二before)、これはそれぞれ一致の後または前の指定された数の行のみを提供します。

次の2つの答えを組み合わせることができます。

find /path/to/files -type f | xargs grep -n -C2 'the_pattern'

それに関するあなたの質問に関しては、sedあなたが提供した例は、あなたがすでに行番号を知っている場合にのみ機能します。次のようにすることもできます。

sed -n '/the_pattern/p' /path/to/files/*

(ただし、サブディレクトリには再帰されません)

答え3

find /media/slowly/DATA/lots_of_files -type f -exec grep -h -C2 'the_pattern' {} +

/media/slowly/DATA/lots_of_filesディレクトリでファイル(ディレクトリやリンクではない)を見つけます。これをグループ化し(この10年間xargsは必要ありません)、grepを実行します。 grepはファイル名(-h)を印刷しませんが、一致する行の前後に2行のコンテキストを提供します(-C2、より正確な制御のために-Aと-Bを使用)。

@cherdtのコマンドと比較して、このコマンドの利点は、findコマンドに追加のフィルタを追加できることです。たとえば、次のディレクトリに入らないように選択できます。.git

関連情報