2

アプリケーションのログファイルを解析するためのPythonスクリプトを作成しています。

ほとんどのログファイルは同様の形式に従います。

09:05:00.342344343 [DEBUG] [SOME_APPLICATION] [SOME_FUNCTION] Lorem ipsum dolor sic amet

通過するさまざまな種類のログラインを解析し、関連するフィールドをPython regexグループ(タイムスタンプ、ログレベル、元のアプリ/関数、およびペイロードのフィールド)に分解するためのさまざまな正規表現があります。

私はこれらの正規表現のそれぞれをdictに保存しました:

foobar_patterns = {
    'pattern1': re.compile(r'blahblahblah'),
    'pattern2': re.compile(r'blahblahblahblah'),
}

ただし、各パターンの間には明らかにかなりの重複があります。タイムスタンプ、ログレベルなどを抽出するための正規表現は共有されます。

この冗長性を取り除く方法はありますか?共通のテンプレートから何らかの方法で差分正規表現文字列を構築できますか?

拡張機能-ファイル内の行をループし、次に、指定された行ごとに、コンパイルされた各正規表現をループします。次に、それに基づいて、それぞれのケースを処理するさまざまな関数があります。たとえば、特定のタイプのメッセージを検出した場合、3行先を検索して他の行を見つけ、そこからフィールドを抽出する必要があります。

foob​​ar_patterns dictにも関数を格納することを考えていました。そして、一致したときにそれを実行しました。

それは物事を行うためのPythonの方法ですか?

乾杯、ビクター

4

5 に答える 5

2
MONTH = r'(?P<month>Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)'
DAY = r'(?P<day>\d{2})'
TIME = r'(?P<hour>\d{2}):(?P<minute>\d{2}):(?P<second>\d{2})'
SPC = r'\s'
HOST = r'(?<host>\w+)'
PREFIX = SPC.join(MONTH, DAY, TIME, HOST)
foobar_patterns = {
    'pattern1': re.compile(PREFIX + r'\s(?<payload>blahbla hbla h blah)'),
    'pattern2': re.compile(PREFIX + r'\s(?<payload>bla h blahbla hblah)'),
}
于 2012-09-21T07:35:25.077 に答える
1

解析を 2 回検討したことはありますか? たとえば、最初のステップで extract timestamplevelApplicationFunctionそしてペイロードを解析しますか? おそらく最初に解析されたログオブジェクトのリストを作成してから、分散したログメッセージを評価する必要があるかもしれません(行を2回解析する必要なく、3行先をスキップするのが簡単になります(必要かもしれません))

または、文字列連結を使用できます。

擬似コード:

basePattern = "\[\w+\]\[\w+\]\[\w+\]"
foobar_patterns {
 'payloadPattern1':'asdf',
 'payloadPattern2':'asdff',
}
for patternKey in foobar_patterns:
    foobar_patterns[patternKey] = re.compile(basePattern + foobar_patterns[paternKey])
于 2012-09-21T07:48:50.163 に答える
1

複雑な正規表現を作成するとき、私はしばしば「文法的」アプローチを使用します。まず、「文法」を辞書として定義します。次に例を示します。

logfile_grammar = {
    'spaces':  '\s+',
    'mname':   '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)',
    'month':   r'\d\d',
    'day':     r'\d\d',
    'year':    r'\d{4}',
    'date':    '(?P<date>($year-$month-$day)|($day $spaces $mname $spaces $year))',
    'payload': '(?P<payload>.+)',
    # more stuff
    'line':    '$date $spaces $payload'
}

ご覧のとおり$xxx、右側は左側のキー (記号) を参照してください。次に、この文法を正規表現に変換します。

def compile_grammar(grammar):
    g = dict(grammar)
    for _ in range(16):
        c = False
        for k, v in g.items():
            w = re.sub(r'\$(\w+)', lambda m: g[m.group(1)], v)
            if w != v:
                g[k] = w
                c = True
        if not c:
            return g
    raise ValueError('too much recursion')

g = compile_grammar(logfile_grammar)    
line_regex = re.compile(g['line'], re.X)

これで、line_regex考えられるすべてのログ行を処理できる 1 つの正規表現が作成されました。

于 2012-09-21T08:45:22.617 に答える
0

重複が多い場合は、すべてのフィールドを一度に抽出する単一の正規表現を使用することを検討してください。

r'(?P<timestamp>\w*) \[(?P<level>\w*)\] \[(?P<application>\w*)\] ...'

この正規表現と一致する場合、結果の一致オブジェクトにはgroupdict()、名前付きグループをプルできるからが含まれます。

于 2012-09-21T07:24:57.233 に答える
0

どうですか:

import re

line = '09:05:00.342344343 [DEBUG] [SOME_APPLICATION] [SOME_FUNCTION] Lorem ipsum dolor sic amet'

ts_pattern = r'\d\d:\d\d:\d\d\.\d+'
name_pattern = r'\[\w+\]'

patterns = [('timestamp', ts_pattern),
            ('log_level', name_pattern),
            ('app_name', name_pattern),
            ('func_name', name_pattern),
            ('payload', '.*$')]

line_pattern = r'\s+'.join('(?P<%s>%s)' % (name, pattern) for name, pattern in patterns)

regex = re.compile(line_pattern)

matches = regex.match(line)

print matches.groupdict()

これにより、次のことが得られます。

{'timestamp': '09:05:00.342344343', 'log_level': '[DEBUG]', 'payload': 'Lorem ipsum dolor sic amet', 'func_name': '[SOME_FUNCTION]', 'app_name': '[SOME_APPLICATION]'}
于 2012-09-21T07:39:25.840 に答える