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


9

大きなファイルテキスト(ほぼ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>

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


2
本当に6月のことですか?サンプルログファイルの日付はすべて7月のものであり、望ましい出力サンプルは後者を意味することを意味します。
David Foerster

回答:


13

では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

11

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

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

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

参照:


1
いつものようにあなたは恵みをもたらします:)
Zanna

(y)...それを機能^させるために削除する必要がありました。Macを使用する。
Anum Sheraz

4

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> 

基本的に開始していることを1から任意の行を出力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を介して、()endtimemktime理解できる形式で指定しますYYYY MM DD hh dd ss。したがってawk、上記のAwkスクリプトがfilter-log-dates.awk現在の作業ディレクトリの実行可能ファイルにあり、ログファイルが次のようであると想定して、コマンドをそのように実行しますmylog.txt

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

終了時刻は排他的であることに注意してください。つまり、有効なログレコードは終了時刻ののタイムスタンプが必要です。

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


3

あなたはそれを段階的に行うことができます。開始パターンに一致する最初の行の番号を見つけます。終了パターンに一致する最後の行の番号を見つけます。次に、これら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)の後にアクションが指定されていないため、デフォルトのアクションは、その範囲の行を印刷することです。

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