3

可能性のある巨大なログファイル(> 50..1000mb)から、指定されたタイムスタンプ「t0」以降の最後の部分を取得したい:

     __________________
    |1 xxx xxx ...     |
    |2 xxx ...         |     uninteresting part
    |4 ...             |
    |...               |
 ___|423 ...           | ___ timestamp t0
    |425 xxx ...       |
    |437 ...           |
    |...               |     <-- i want this part ( from t0 to EOF)
    |__________________|

追加の制約は、単純なbashコマンドを使用してこれを実行したいということです。簡単な解決策は次のとおりです。

awk '$1 > 423' file.log

しかし、これはすべての意図しない行を含むファイル全体をスキャンします。コマンドテールがありますが、私は彼に私が知らない最後の行の数を与えることができます-私はタイムスタンプを知っているだけです。最初のタイムスタンプが一致しないときに後ろから「目覚め」て処理を停止する方法はありますか?

4

4 に答える 4

4

tacはここであなたの友達です:

tac file.log | awk '{ if ($1 >= 423) print; else exit; }' | tac

tacは、ファイルの各行を最後の行からダンプし、ファイルの先頭まで処理します。必要な行を取得するために一度実行してから、順序を修正するためにもう一度実行します。

于 2011-04-30T19:17:26.317 に答える
1

私が正しく理解していれば、タイムスタンプ正規表現からファイルの終わりまでのn行を取得する必要があります。

あなたの巨大なファイルは次のようなものだと言わないでください:

~$ cat > file << EOF
rubish
n lines of rubish
more rubish
timestamp regexp
interesting
n interesting lines
interesting
end of file
EOF

探しているタイムスタンプの実行可能な正規表現を取得できる場合は、sedを使用して必要な部分を取得できます。

~$ sed -n '/timestamp regexp/,$ {p}' file
timestamp regexp
interesting
n interesting lines
interesting
end of file
于 2011-04-29T13:49:15.627 に答える
1

標準のUnixコマンドを使用すると、ファイル全体をスキャンする以外にできることはほとんどありません。独自のプログラムを作成する場合は、ファイルに対してバイナリ検索を実行できます。

  • ファイル内のポイントを探し、
  • 記録の次の開始に転送を読み、
  • タイムスタンプが大きすぎるか小さすぎるかを確認します。
  • ファイル内で正しいポイントが見つかるまで繰り返します。

タイムスタンプが純粋な数値である場合は、純粋な2分探索ではなく、線形補間を使用して検索を行うこともできます。スタンプがより複雑な場合は、おそらく追加のコーディングの価値はありませんが、これが必要になる頻度によって異なります。

確かに、これを頻繁に実行し、パフォーマンスが問題であることを示すことができない限り、私は単純なawk解決策を採用します。

于 2011-04-29T14:04:03.453 に答える
0

「423」を押すまでポーリングできます。単なる架空の例(テストされていません)

n=100 # number of lines you want to go back
while true
do
  if tail -$n file | grep -q "423" ;then
     tail -$n file | awk '$1>423'
     break
  else
     ((n+=100)) # increment every 100 lines
  fi
done
于 2011-04-29T08:07:29.030 に答える