ログファイルから一部を切り取る方法は?


18

8 Gbのログファイル(Railsの運用ログ)があります。いくつかの日付(行)の間にカットする必要があります。これを行うにはどのコマンドを使用できますか?


1
皆さん、この質問は大きなファイルに関するものなので、「アンティアップ!」です。時間の問題です... 85904064行(行あたり100文字)の実際の8 GBファイルで、お気に入りのsedスクリプトをテストしました。私はsedが大好きですが、現状では、sedスクリプトは毎回ファイル全体をスキャンします。(?)これは、それが終了したときに、-たawkスクリプトのように遅い、平均二倍に...私はsedスクリプトを考えさせることだけで第二の発現のためにdの代わりAQ必要が...テスト結果はここにある:ペースト.ubuntu.com / 573477 ..また、適切な出力を生成しません.. asoundmoveの答えの最後に私のコメントを参照してください。
Peter.O

asoundmoveの新しいsedバージョンは速度の問題に対処しており、awksの速度と一致するようになりました。新しいバージョンはデータを正しく出力するようになりました...詳細については彼のコメントをご覧ください。
Peter.O

「カット」(通常は削除を意味します)と言っていることに気づきました。本当に「カット」という意味ですか、それとも「コピー」という意味ですか?....「カット」を意味した場合、sed簡単に実行できます。
Peter.O

回答:


12

何かのようなもの

sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less

tee cut-logファイルに何を入れているかを画面で見ることができますcut-log

編集:

fred.bearの厳格な基準を満たすために、sedソリューションがあります(おそらくawkソリューションはかなりきれいです)。

b=BB; e=EE ;echo -e "AA\nAA\nBB\nBB\nCC\nCC\nDD\nDD\nEE\nEE\nFF\nFF" | sed -n ":b;/$b/b p;n;b b;:p;p;n;/$e/b e;b p;:e;p;n;/$e/b e;q"


3
@dogbane:ええ、ええ。編集済み。私はあなたが時々最適なコードよりも少ないコードを書くと確信しています、それはそのような厳しいコメントに値しますか?
asoundmove

1
注:同じ日付の複数の連続した「最初の日付」行がある場合、最初の行以外はすべて削除され、出力に導入されます...注意すべきこと...状況)
Peter.O

1
...しかし、私が賛成の++であるにもかかわらず、この特定の仕事は、自分の個人的なツール以外の何かのために、その限界を超えていると思います。私はあなたと同じようにsedを取得することができました.. 1%以内で実行されました)..メインの問題に戻ります。(awkには適用されません)....バグ(修正不可):ログの範囲内で有効であるが、実際にはログに存在しない日付に関しては、1番目の引数の場合、sedは何も出力せず、2番目の引数の場合、sedはすべてを出力します最初の日付の後!...詳細
...-Peter.O

1
別の修正可能なバグ:現在、データプロションを含む任意の行の日付に一致しますが、それは単なる正規表現の調整です。そして、それを使用したい人は、おそらく引数が最初を参照し、範囲内の最後の日付(-1と+1ではない)..そして最後に..私の「厳密な基準」は私のものではありません。私は質問者のリクエストのメッセンジャーです...ユーザー、リクエストされたとおりに機能するかどうかに気付くでしょう。これは私にとって素晴らしい質問でした。それが速度にsed匹敵することを知るawkために、それは実際には少し速かった。
Peter.O

6

FOOからBARまでのすべてを含めて印刷するには、次を試してください。

$ sed -n '/FOO/,/BAR/p' file.txt

1
注:これは、一連の連続したバーの最初のBARのみを印刷します
...-Peter.O

別の注意...日付のいずれかがデータに存在しない場合の大きな問題..最終日付が存在しない場合、sedはEOFに達するまで行を出力し続けます。
-Peter.O

5

これにより、必要な処理が行わ
れます。パラメータの日付を含めることと除外することの両方が表示されます。

# set Test args
set  2011-02-24  2011-02-26  "junk"

from="$1"
till="$2"
file="$3"

# EITHER ====                              +++++++++  
# Ouptut lines between two parameter dates INCLUDING the parameter dates
  awk -v from=$from -v till=$till '
    ($2 >= from) && ($2 <= till) { print $0 ; next }
    ($2 > till) { exit }' "$file"

# OR ========                              ---------
# Ouptut lines between two parameter dates EXCLUDING the parameter dates
  awk -v from=$from -v till=$till '
    ($2 > from) && ($2 < till) { print $0 ; next }
    ($2 >= till) { exit }' "$file"

フィールド2の(ソートされた)日付をテストします...テストデータの例を次に示します

    98  2011-02-05 xxxx
    99  2011-02-05 xxxx
   100  2011-02-06 xxxx
   101  2011-02-06 xxxx

そして、これがtest-data generatorです。


私はそれをもう少し簡単に(たとえば最初のものを)書きます: awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
asoundmove

@asoundmove:はい、それは良く見えるかもしれませ、そしてそれは間違いなくより慣習的ですが、実際には、その実行時間は合計で1つの余分なifステートメントの持続時間です(1行あたり1でもない)。ロジックフローは事実上同じで、実行時間の差はナノ秒単位でカウントされます。「else」を使用しなかった唯一の理由は、これが事実上私の初めてのスクリプト(1日4年を除く)前、私は)いくつかの例と共演...それが述べたように、私は...見つかった(と最初の実行可能な分岐メカニズムであるとき、それは)同じように高速です..私generly使用。トライawksedq
Peter.O

このメソッドでテキストファイルの名前と場所を指定する場所がわかりませんか?誰かが私の愚かさを見抜くのを手伝ってくれる
ジャイルズ

4

ログファイルにこの形式の日付がある場合、YYYY-MM-DDたとえば2011-02-10のすべてのエントリを見つけるには、次のようにします。

grep 2011-02-10 log_file

ここで、2011-02-10と2011-02-11のエントリを検索する場合、もう一度使用しますgrepが、複数のパターンを使用します。

grep -E '2011-02-10|2011-02-11' log_file

良い。「広告どおり」に機能します:) ...ただし、grep日付範囲がファイルの先頭にある場合でも、ファイル全体を検索します。これは、「範囲内の最後のアイテムの終了」と比較すると、平均して検索時間を2倍にします。質問で言及されている8 GBのファイルサイズのため、 grep時間の結果は、ここのsedの例とほぼ同じです(1分58秒)。タイムテストの結果へのリンクを次に示します。paste.ubuntu.com
Peter.O

1

このサイズのファイルでの作業は常に困難です。

次の方法は、このファイルをいくつかの小さなファイルに分割することです。これを行うには、splitコマンドを使用します。

split -d -l 50000 ToBigFile.data file_

分割されても、bash forループを使用する場合のようにファイルを操作できます。

for f in `ls file_*`; do cat $f; done;

しかし、猫の代わりに、逆grepを使用して不要なデータを取り除くことができます。これはこれには関係ありません。(または必要な改良の種類)。

この時点で、多くの小さなファイルを操作するだけで、他の上記のコマンドは、多くの小さなファイルを処理します。

そして、完了したら、2番目のforループを使用して、新しい小さなファイルを再度作成します。

for f in `ls file_*`; do cat $f >> NewFile.data ; done;

更新 データを複数のファイルに分割し始めるため、ハードドライブで多くの作業が必要になり、時間がかかります。(この質問ではどうやら5分)。

一方、次の手順はおそらくより高速です。

したがって、この方法は単純なgrep、awk、sed操作にはおそらく意味がありませんが、検索パターンがより複雑になると、より高速になる可能性があります。


3
Johanm、私のコンピューターで8 GBのログファイルを検索するにはawkとsedを平均1分しかかからず、同じコンピューターで最初のファイル分割だけで4分43秒かかります... :)
Peter.O

小さいファイルでこれらのawkとsedの時間を50%削減できるとしましょう。その後、合計時間を得る前に、これらの操作を10回以上行う必要があります。そのため、ファイル分割は、いくつかの回帰では最良のアイデアではないかもしれません
Johan

awkスクリプトは(簡単に)10個の異なる検索結果を10個のファイルに1回のパスで出力するように変更できますが、実際にレポートを出力している間は読み込みが遅くなります... Sedも同じことができますが、 'asoundmoveのコメントで言及したように、特定の日付/時刻にログのエントリがない場合、sedは失敗します(たとえば、1時間ごとに検索しています)。sedを頻繁に使用し、非常に便利ですが、制限があります... sed vs awkをいつ使用するかについてのsed FAQです。必ずしもすべてに同意するわけではありませんが、その意味はわかります... sed.sourceforge.net/sedfaq6.html
Peter。 O

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.