1

分析する必要があるテキスト ファイルがあります。ファイルの各行は次の形式です。

7:06:32 (slbfd) IN: "lq_viz_server" aqeela@nabltas1  

7:08:21 (slbfd) UNSUPPORTED: "Slb_Internal_vlsodc" (PORT_AT_HOST_PLUS   ) Albahraj@nabwmps3  (License server system does not support this feature. (-18,327))

7:08:21 (slbfd) OUT: "OFM32" Albahraj@nabwmps3

タイムスタンプとをスキップ(slbfd)し、IN と OUT の行数だけを保持する必要があります。さらに、引用符で囲まれた名前に応じて、行がで始まる場合はさまざまな変数の変数カウントを増やし、OUTそれ以外の場合は変数カウントを減らす必要があります。Pythonでこれを行うにはどうすればよいですか?

4

5 に答える 5

5

正規表現と行の分割を使用した他の回答は仕事を終わらせますが、あなたと共に成長する完全に保守可能なソリューションが必要な場合は、文法を構築する必要があります. 私はこれが大好きpyparsingです:

S ='''
7:06:32 (slbfd) IN: "lq_viz_server" aqeela@nabltas1  
7:08:21 (slbfd) UNSUPPORTED: "Slb_Internal_vlsodc" (PORT_AT_HOST_PLUS   ) Albahraj@nabwmps3  (License server system does not support this feature. (-18,327))
7:08:21 (slbfd) OUT: "OFM32" Albahraj@nabwmps3'''

from pyparsing import *
from collections import defaultdict

# Define the grammar
num = Word(nums)
marker = Literal(":").suppress()
timestamp = Group(num + marker + num + marker + num)
label = Literal("(slbfd)")
flag = Word(alphas)("flag") + marker
name = QuotedString(quoteChar='"')("name")

line    = timestamp + label + flag + name + restOfLine
grammar = OneOrMore(Group(line))

# Now parsing is a piece of cake!  
P = grammar.parseString(S)
counts = defaultdict(int)

for x in P:
    if x.flag=="IN": counts[x.name] += 1
    if x.flag=="OUT": counts[x.name] -= 1

for key in counts:
    print key, counts[key]

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

lq_viz_server 1
OFM32 -1

サンプル ログ ファイルがもっと長いと、より印象的になります。pyparsing ソリューションの優れた点は、将来、より複雑なクエリに適応できることです (例: タイムスタンプの取得と解析、電子メール アドレスのプル、エラー コードの解析など)。アイデアは、クエリとは独立して文法を記述することです。生のテキストをコンピューターに適した形式に変換するだけで、構文解析の実装をその使用法から切り離して抽象化できます。

于 2012-06-22T14:39:53.820 に答える
1

次の 2 つのオプションがあります。

  1. .split()の機能を使用しますstring(コメントで指摘されているように)
  2. reモジュールを正規表現に使用します。

reモジュールを使用して、名前付きグループでパターンを作成することをお勧めします。

レシピ:

  • re.compile()最初に、名前付きグループを含むパターンを作成します
  • forファイルをループして、行が使用する行を取得し.match()ます
  • を使用して各行にパターンオブジェクトを作成しまし.groupdict()
  • 対象の値にアクセスするための一致オブジェクトを返しました
于 2012-06-22T14:29:00.730 に答える
1

ファイルが行に分割されていると考える場合 (本当かどうかはわかりません) split()、各行に関数を適用する必要があります。あなたはこれを持っています:

["7:06:32", "(slbfd)", "IN:", "lq_viz_server", "aqeela@nabltas1"]  

そして、必要な値を比較するロジックを適用できる必要があると思います。

于 2012-06-22T14:29:10.293 に答える
1

私はあなたの仕様についていくつかのワイルドな仮定をしました。ここにあなたが始めるのに役立つサンプルコードがあります:

objects = {}
with open("data.txt") as data:
    for line in data:
        if "IN:" in line or "OUT:" in line:
            try:
                name = line.split("\"")[1]
            except IndexError:
                print("No double quoted name on line: {}".format(line))
                name = "PARSING_ERRORS"
            if "OUT:" in line:
                diff = 1
            else:
                diff = -1
            try:
                objects[name] += diff
            except KeyError:
                objects[name] = diff
print(objects) # for debug only, not advisable to print huge number of names
于 2012-06-22T14:31:49.890 に答える
0

標準ディストリビューションでただやり遂げるモードでは、これは機能します:

import re
from collections import Counter
# open your file as inF...
count=Counter()
for line in inF:
    match=re.match(r'\d+:\d+:\d+ \(slbfd\) (\w+): "(\w+)"', line)
    if match:
        if match.group(1) == 'IN': count[match.group(2)]+=1
        elif match.group(1) == 'OUT': count[match.group(2)]-=1

print(count)

版画:

Counter({'lq_viz_server': 1, 'OFM32': -1})
于 2012-06-22T15:29:28.710 に答える