web-dev-qa-db-ja.com

大きなテキストファイルでgrep / sedを使用して日付の範囲からテキストを取得する方法

大きなファイルテキスト(ほぼ3 GB)があります-これはログファイルです。このファイルから、7月13日から7月19日までの日付範囲に対応するテキスト行を取得したい。私のログ形式は次のとおりです。

2016-07-12 < ?xml version>
2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>
2016-07-20 < ?xml version>
sample text sample text
sample text sample text
sample text sample text
2016-07-20 < ?xml version>
sample text sample text
2016-07-20 < ?xml version>

grep/sedの後、次のように出力されます。

2016-07-13 < ?xml version>
2016-07-18 < ?xml version>
2016-07-18 < ?xml version>
2016-07-19 < ?xml version>

どうすれば入手できますか?

8
corey

grepを使用すると、必要な行数がわかっている場合は、コンテキストオプション-Aを使用して、パターンの後の行を印刷できます。

grep -A 3 2016-07-13 file

2013-07-13の行と次の3行が表示されます

sedを使用すると、日付を使用してこのように区切ることができます

sed -n '/2016-07-13/,/2016-07-19/p' file

2016-07-13の最初の行から2016-07-19の最初の行までのすべての行を印刷します。ただし、2016-07-19では1行しかないことを前提としています(次の行は印刷されません)。複数の行がある場合は、代わりに次の日付を使用し、dを使用して出力を削除します

sed -n '/2016-07-13/,/2016-07-20/{/2016-07-20/d; p}' file
12
Zanna

この単純なgrep one linerで十分です:

grep -E ^2016-07-1[3-9] filename

ここではうまく機能し、sedは必要ありません:)

参照:

10
andrew.46

awkソリューション:

$ awk '/^2016-07-13.*/,/2016-07-19.*/'  input.txt                                   
2016-07-13 < ?xml version> 
2016-07-18 < ?xml version> 
2016-07-18 < ?xml version> 
2016-07-19 < ?xml version> 

基本的に、2016-07-13で始まる行から2016-07-19で始まる行までのすべての行を出力します

4

他のすべての現在の回答は、ログファイルエントリが時系列でソートされているという事実、または日付範囲を正規表現と簡単に一致させることができるという事実に依存しています。より一般的なソリューションが必要な場合は、さらにプログラミングを行う必要があります。

このGNU AWKスクリプトを紹介します。

#!/usr/bin/gawk -f
BEGIN {
    starttime = mktime(starttime)
    endtime = mktime(endtime)
}

func in_range(n, start, end) {
    return start <= n && n < end
}

match($0, /^([0-9]{4})-([0-9]{2})-([0-9]{2})\s/, m) &&
    in_range(mktime(m[1] " " m[2] " " m[3] " 00 00 00"), starttime, endtime)

開始時間と終了時間は、変数starttimeおよびendtimeを使用して、 mktime が理解できる形式(YYYY MM DD hh dd ss)で指定します。したがって、上記のAwkスクリプトが現在の作業ディレクトリの実行可能ファイルfilter-log-dates.awkにあり、ログファイルがmylog.txtであると仮定して、awkコマンドを次のように実行します。

./filter-log-dates.awk -v starttime='2016 07 13 00 00 00' -v endtime='2016 07 20 00 00 00' mylog.txt

終了時間はexclusive、iです。 e。有効なログレコードにはタイムスタンプが必要ですbefore終了時刻。

タイムスタンプの形式が異なる場合は、match関数に渡される正規表現を調整して調整できます。

4
David Foerster

手順を踏んで行うことができます。開始パターンに一致する最初の行の番号を見つけます。終了パターンに一致する最後の行の番号を見つけます。次に、これらの2行の間のテストを抽出します。これは次のように実行できます。

grep -n 2016-07-13 bigtextfile | head -1
grep -n 2016-07-19 bigtestfile | tail -1
# Say the first number is 1234 and the second 5678, then use...
awk 'NR>=1234 && NR<=5678' bigtestfile > rangeoftext

これはすべてawkコマンドで実行できますが、手順を実行することで簡単に実行できる場合があります。 awk内のNR変数は現在の行番号であり、パターン(NR> = 1234 && NR <= 5678)の後にアクションが指定されていないため、デフォルトのアクションはその範囲の行を印刷することです。

3
Jeffrey Ross