web-dev-qa-db-ja.com

grep式に一致する行の後のファイルの一部を取得する方法は? (最初の一致)

約1000行のファイルがあります。 grepステートメントに一致する行の後のファイルの一部が必要です。

つまり.

$ cat file | grep 'TERMINATE'     // Its found on line 534

そのため、さらに処理するために535 to line 1000行のファイルが必要です。

どうすればいいのですか ?

155
Yugal Jindle

簡単な近似として、使用できます

grep -A100000 TERMINATE file

TERMINATEを取得し、その行に続く最大100000行を出力します。

マニュアルページから

-A NUM, --after-context=NUM

一致する行の後に末尾コンテキストのNUM行を印刷します。隣接する一致グループの間にグループ区切り文字(-)を含む行を配置します。 -oまたは--only-matchingオプションでは、これは効果がなく、警告が表示されます。

60
aioobe

ここで使用するツールはawkです。

cat file | awk 'BEGIN{ found=0} /TERMINATE/{found=1}  {if (found) print }'

これはどのように作動しますか:

  1. 変数 'found'をゼロに設定し、falseを評価します
  2. 正規表現で「TERMINATE」に一致するものが見つかった場合、それを1に設定します。
  3. 「found」変数の評価がTrueの場合、印刷します:)

他のソリューションは、非常に大きなファイルで使用すると、多くのメモリを消費する可能性があります。

26
Jos De Graeve

次のようなbashパラメーター展開を使用します。

content=$(cat file)
echo "${content#*TERMINATE}"
7
Mu Qiao

あなたの質問を正しく理解しているなら、行afterTERMINATEが必要です。TERMINATE- lineは含まれていません。 awkは簡単な方法でこれを行うことができます。

awk '{if(found) print} /TERMINATE/{found=1}' your_file

説明:

  1. ベストプラクティスではありませんが、すべての変数がデフォルトで0または定義されていない場合は空の文字列にデフォルト設定されているという事実に頼ることができます。したがって、最初の式(if(found) print)は最初から何も出力しません。
  2. 印刷が完了したら、これがスターターライン(含まれてはならない)かどうかを確認します。

これにより、すべての行が出力されます the TERMINATE- line。


一般化:

  • start-およびend-linesのファイルがあり、それらの行の間の行が必要な場合exexceptstart -およびend-lines。
  • start-およびend-linesは、その行に一致する正規表現で定義できます。

例:

$ cat ex_file.txt 
not this line
second line
START
A good line to include
And this line
Yep
END
Nope more
...
never ever
$ awk '/END/{found=0} {if(found) print} /START/{found=1}' ex_file.txt 
A good line to include
And this line
Yep
$

説明:

  1. end-lineが見つかった場合、印刷は行われません。このチェックが行われることに注意してくださいbefore実際の印刷結果からend-lineを除外します。
  2. foundが設定されている場合、現在の行を印刷します。
  3. start-lineが見つかった場合、found=1を設定して、次の行が出力されるようにします。このチェックが行われることに注意してくださいafter結果からstart-lineを除外する実際の印刷。

ノート:

  • このコードは、すべてのawk-varsのデフォルトが0または定義されていない場合は空の文字列であるという事実に依存しています。これは有効ですが、ベストプラクティスではないため、awk-expressionの先頭にBEGIN{found=0}を追加できます。
  • 複数のstart-end-blocksが見つかった場合、それらはすべて出力されます。
7
UlfR

grep -A 10000000「TERMINATE」ファイル

  • sedよりもはるかに高速で、特に実際に大きなファイルを処理します。最大1,000万行(または入力したもの)で動作するため、ヒットしたものすべてを処理するのに十分な大きさにするのに問題はありません。
4
user8910163

何らかの理由でsedの使用を避けたい場合、次のコマンドはTERMINATEに一致する行をファイルの最後まで出力します。

tail -n "+$(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)" file

そして、以下はTERMINATEに一致する次の行からファイルの最後まで印刷されます。

tail -n "+$(($(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)+1))" file

Sedが1つのプロセスで実行できることを行うには2つのプロセスが必要です。grepの実行とtailの実行中にファイルが変更されると、結果が不整合になる可能性があるため、sedの使用をお勧めします。さらに、ファイルdonesにTERMINATEが含まれていない場合、最初のコマンドは失敗します。

3
jfg956

sedまたはawkでそれを行うには多くの方法があります。

sed -n '/TERMINATE/,$p' file

これは、ファイル内でTERMINATEを探し、その行からファイルの最後まで出力します。

awk '/TERMINATE/,0' file

これは、sedとまったく同じ動作です。

印刷を開始する行の番号がわかっている場合は、NR(最終的に行の番号を示すレコードの数)と一緒に指定できます。

awk 'NR>=535' file

$ seq 10 > a        #generate a file with one number per line, from 1 to 10
$ sed -n '/7/,$p' a
7
8
9
10
$ awk '/7/,0' a
7
8
9
10
$ awk 'NR>=7' a
7
8
9
10
2
fedorqui

これは、それを行う1つの方法です。ファイルのどの行にgrep Wordがあり、ファイルに何行あるかがわかっている場合:

grep -A466 'TERMINATE'ファイル

0
Mariah

Jfgagneによる優れたsedの回答に代わるもので、一致する行が含まれていません。

0
mivk