web-dev-qa-db-ja.com

文字列を含む行を見つけて、それらの特定の行と何か他のものを印刷する方法

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

    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

両方のステップを1つのコマンドに組み合わせる方法はありますか?行番号とファイル名をsedにパイプして、行を出力することを考えています。 grepの出力が生成される順序に問題があります。

Q1b

上記と同じですが、文字列を含む行の前後2行も印刷します(合計5行)?行番号とファイル名をsedにパイプし、必要なすべての行を何らかの方法で出力することを考えています。

本当にありがとう。

8
speld_rwong

質問を正しく理解していれば、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

出力では、一致する行(:)とコンテキスト行(-)に異なる区切り文字が使用されていることに注意してください。

6
cherdt

あなたの最初の質問は、私が知る限り、別の方法でgrepにアクセスすることで回答できます。ファイルのリスト(または-rまたは-Rで再帰するディレクトリ)を送信すると、常に、一致したファイルと行番号が出力されます。次のような構成でこれを回避できます。

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

2番目の質問については、一致の前後の行を表示する場合は、-Cを使用できます([〜#〜] c [〜#〜] ontextの場合)スイッチ:

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

-Cに関連するのは、-A(for [〜#〜] a [〜#〜] fter)と-B(for [〜 #〜] b [〜#〜] efore)、それぞれ一致の後または前に指定された行数のみを与えます。

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

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

sedに関する質問については、指定した例は、行番号がわかっている場合にのみ機能します。次のようなこともできます:

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

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

0
DopeGhoti
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のようなディレクトリに移動しないように選択できます。

0
icarus