特定のファイルで特定の文字列を検索したい。文字列が見つかった場合は、その行の前(または後)に行X行も印刷します。
これをgrepまたはawkで実行できますか、それとも組み合わせが必要ですか?
this のようなものが欲しいのですが、ヒットの前後のすべての後続/先行行ではなく、X番目だけです。
たとえば、私の入力が次のようになっているとします。
line1 with a pattern
line2
line3
line4 with a pattern
line5
line6
line7 with a pattern
...
私は「パターン」という単語を検索し、その行+ 2行後の行を出力しますが、パターンの行の直後に続く行は出力しません。したがって、望ましい出力は次のとおりです。
line1 with a pattern
line3
line4 with a pattern
line6
line7 with a pattern
...
grep
は、オプション-A
(後)と-B
(前)、および-C
(コンテキスト)を使用してこれを行います。私がよく使用する例は次のとおりです。
Sudo lspci -vnn | grep -i net -A 12
このコマンドは、一致後の12行を表示します。これには、ネットワーク(-i net)カードの制御に使用されるドライバーが含まれます。一般に、コマンドは次のとおりです。
grep text_to_search -A n -B m file.extension
マッチの前にm
行、マッチの後にn
行を出力します。または使用できます
grep text_to_search -C n file.extension
見つかったテキストを囲む合計n
行を表示します(一致の前半分、一致後の半分)。
この質問を少し調べた後、標準のGNUスクリプトを使用しないツールを使用して、実現可能性についてのコメントを修正する必要があると思います。これはvery特別なケースの。
あなたがawkを使うことを気にしないなら、私は次の解決策を提供することができます。このスクリプトcontext.awk
は、まだ簡潔ではありません。
{
lines[NR] = $0
if (dump[NR]) {
print $0;
if ($0 ~ Pattern) {
if (NR-Delta in lines) {
print "---"
print lines[NR-Delta]
}
dump[NR+Delta] = 1
print $0;
}
if (NR-Delta in lines)
delete lines [NR-Delta];
}
次のように呼び出す必要があります。
awk -v Delta=X -v Pattern=PATTERN -f context.awk sample.txt
ここで、X
は目的の「コンテキスト距離」であり、PATTERN
は検索パターンです。スクリプトは、---
を間に挟んで行を出力することにより、ファイル内の複数のパターンコンテキストを分離しようとします。したがって、たとえば、次のsample.txt
line1
line2
line3 XXX
line4
line5
line6
line7 XXX
line8
line9
line10 XXX
line11
この呼び出しを使用して
awk -v Delta=3 -v Pattern=XXX -f context.awk sample.txt
次の出力を生成します
line3 XXX
line6
---
line4
line7 XXX
line10 XXX
---
line7 XXX
line10 XXX
次のsed
コマンドは、私がどのように表現するかを記述した場合に機能するようです。パターンに一致する行を印刷し、直後の行を印刷せず、パターンの2行後の行も印刷し、そのまま保持します。パターンマッチを検索します。
sed -n -e '/with a pattern/ {h;n;n;H;x;p}' file
少し見苦しいようですが、n
(行をスキップして次の行に移動する)およびH
(保留バッファーに追加してこの行を保持する)コマンドを追加することで、パターン一致後の任意の保持/スキップ関係。
一致に続いて、最初にh
コマンドを使用して一致する行を保持バッファーにコピーすることに注意してください。最後に、ホールドとパターンスペースをx
と入れ替え、パターンスペースをp
と出力します。この時点で、sed
はファイルを1行ずつ処理し続け、別の一致を探します。
sed
コマンドの便利なリファレンスは here にあります。
grep -A2 <pattern> file | grep -B1 <pattern> | grep -v "\-\-"
は私のために働きます:
user@box /tmp $ grep -A2 "with a pattern" test.txt | grep -B1 "with a pattern" | grep -v "\-\-"
line1 with a pattern
line3
line4 with a pattern
line6
line7 with a pattern
user@box /tmp $ cat test.txt
line1 with a pattern
line2
line3
line4 with a pattern
line5
line6
line7 with a pattern