次のコマンドを使用して複数のファイルを再帰的に検索し、文字列が見つかった各ファイルの行番号を見つけます。
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にパイプし、必要なすべての行を何らかの方法で出力することを考えています。
本当にありがとう。
質問を正しく理解していれば、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
出力では、一致する行(:
)とコンテキスト行(-
)に異なる区切り文字が使用されていることに注意してください。
あなたの最初の質問は、私が知る限り、別の方法で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/*
(ただし、サブディレクトリに再帰しません)
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
のようなディレクトリに移動しないように選択できます。