2

現在、次の構造のログファイルを解析しています。

1)タイムスタンプ、前に#文字、後に\ n

2)そのタイムスタンプの後に発生し、その後にすべて\nが続く任意の数のイベント

3)繰り返します。

次に例を示します。

#100
04!
03!
02!
#1299
0L
0K
0J
0E
#1335
06!
0X#
0[#
b1010 Z$
b1x [$
...

一見不可解な値をご容赦ください。これらは特定の「イベント」を表すエンコーディングです。

注:イベントエンコーディングでも#文字を使用できます。

私がやろうとしているのは、特定の時間に発生するイベントの数を数えることです。

つまり、タイム100で、3つのイベントが発生しました。

2つのタイムスタンプの間のすべてのテキストを一致させようとしています。一致したテキストで囲まれた改行の数を数えるだけで、イベントの数を数えます。

Pythonの正規表現エンジンを使用しており、次の式を使用しています。

pattern = re.compile('(#[0-9]{2,}.*)(?!#[0-9]+)')

注:{2、}は、少なくとも2桁のタイムスタンプが必要なためです。

タイムスタンプを照合し、別のタイムスタンプに到達するまで他の文字の照合を続けます-照合を終了します。

これが返すものは次のとおりです。

#100
#1299
#1335

だから、私はタイムスタンプを取得しますが、イベントデータはありません-私が本当に気にかけていることです!

その理由は、ネガティブな後ろ姿が「貪欲」だと思っていますが、完全にはわかりません。

これをはるかに簡単にする完全に異なる正規表現があるかもしれません-どんな提案にもオープンです!

どんな助けでも大歓迎です!

-k

4

4 に答える 4

2

正規表現は、ここでの作業に適したツールではないと思います。ループを使用するだけです。

>>> import collections
>>> d = collections.defaultdict(list)
>>> with open('/tmp/spam.txt') as f:
...   t = 'initial'
...   for line in f:
...     if line.startswith('#'):
...       t = line.strip()
...     else:
...       d[t].append(line.strip())
... 
>>> for k,v in d.iteritems():
...   print k, len(v)
... 
#1299 4
#100 3
#1335 6
于 2012-09-17T01:43:07.280 に答える
1

正規表現ベースのソリューションを主張する場合、私はこれを提案します:

>>> pat = re.compile(r'(^#[0-9]{2,})\s*\n((?:[^#].*\n)*)', re.MULTILINE)
>>> for t, e in pat.findall(s):
...     print t, e.count('\n')
...
#100 3
#1299 4
#1335 6

説明:

(              
  ^            anchor to start of line in multiline mode
  #[0-9]{2,}   line starting with # followed by numbers
)
\s*            skip whitespace just in case (eg. Windows line separator)
\n             new line
(
  (?:          repeat non-capturing group inside capturing group to capture 
               all repetitions
    [^#].*\n   line not starting with #
  )*
)

あなたはネガティブな先読みが何をするのか誤解しているようでした。に続く.*場合、正規表現エンジンは最初にできるだけ多くの文字を消費しようとし、次に先読みパターンをチェックします。先読みが一致しない場合は、一致するまで文字ごとにバックトラックします。

ただし、貪欲でないものと一緒に前向きな先読みを使用することはできます.*?。ここで、.*?は、先読みで行の先頭に#が表示されるか、文字列全体の末尾が表示されるまで、文字を消費します。

re.compile(r'(^#[0-9]{2,})\s*\n(.*?)(?=^#|\Z)', re.DOTALL | re.MULTILINE)
于 2012-09-20T12:11:37.850 に答える
1

その理由は、ドットが改行と一致しないため、式はタイムスタンプを含む行とのみ一致するためです。試合は複数の行にまたがることはありません。「dotall」フラグをに渡しre.compileて、式が複数の行で一致するようにすることができます。「イベントエンコーディング」にも#文字が含まれている可能性があるため、複数行フラグを使用して、行^の先頭にのみ一致するように、最初に一致を固定することもでき#ます。

于 2012-09-17T01:23:32.010 に答える
1

データを1行ずつループして、各タイムスタンプに関連付けられたイベントの数を格納するだけの辞書を作成できます。正規表現は必要ありません。例えば:

with open('exampleData') as example:
    eventCountsDict = {}
    currEvent = None
    for line in example:
        if line[0] == '#': # replace this line with more specific timestamp details if event encodings can start with a '#'
            eventCountsDict[line] = 0
            currEvent = line
        else:
            eventCountsDict[currEvent] += 1

print eventCountsDict

そのコード{'#1299\n': 4, '#1335\n': 5, '#100\n': 3}は、サンプルデータ用に出力されます(はカウントされません...)。

于 2012-09-17T01:24:24.940 に答える