Mamy plik z następującymi liniami, musimy znaleźć wszystkie linie z typem komunikatu "Error". Zapisz wiadomość i jego liczbę oraz wydrukować wiadomości w kolejności malejąco to?

File.txt.

<TIMESTAMP><MESSAGETYPE><MESSAGE>
<4:02><ERROR><Error message1>
<14:13><Error><Error message2>
<10:03><Warning><Warning message1>
<12:03><Warning><Warning message2>

KOD:-

-7
user3508811 25 czerwiec 2017, 00:19

4 odpowiedzi

Najlepsza odpowiedź
  1. Otwórz plik i przeczytaj wszystkie linie
with open("file.txt") as f:  
    lines = f.read().splitlines()
  1. Zrób listę linii zawierających słowo "błąd"
data = [ line.lstrip('<').rstrip('>').split('><') for line in lines if 'Error' in line  ]
  1. Zdobądź czas i wiadomości z listy data
errors = [ { 'time' : line[0], 'message': line[-1] } for line in data ]  
  1. Sortuj listę errors przez "czas" w kolejności malejącym
errors.sort(key=lambda e : e['time'], reverse=True)  

Należy pamiętać, że errors jest listą słowników, możesz użyć list, jeśli chcesz.
Jeśli chcesz wydrukować wyniki:

print '\n'.join( 'Time {:8} Error {}'.format(e['time'], e['message']) for e in errors )

Wynik :

Time: 4:02   Error: Error message1
Time: 14:13  Error: Error message2
4
t.m.adam 5 lipiec 2017, 08:19

Korzystanie z Light klasa

from re import compile, IGNORECASE
from collections import Counter
from operator import itemgetter

parse = compile(r'<(?P<ts>.*)><(?P<level>ERROR)><(?P<message>.*)>', IGNORECASE)

with open('file.txt') as f:
    logs = filter(None, map(parse.match, f))
    counts = Counter(log.group('message') for log in logs)

print sorted(counts.items(), key=itemgetter(1), reverse=True)


>>> [('Error message1', 1), ('Error message2', 1)]
1
Mike Robins 12 lipiec 2017, 04:13

Możesz zrobić coś takiego:

from collections import defaultdict
import operator
import re

def find_error_message(string):
    match = re.search(r"<\d{1,2}:\d{2}><(ERROR|Error)><(?P<message>[a-zA-z0-9 ]*)>(\n)?", string)
    if match:
        return match.group("message")

messages = defaultdict(int)
with open(r"log.txt", "r") as fh:
    lines = fh.readlines()

lines.pop(0)
for line in lines:
    message = find_error_message(line)
    if message:
        messages[message] += 1
for message, count in sorted(messages.items(), key=operator.itemgetter(1), reverse=True):
    print("{}: {}".format(message, count))

Funkcja find_error_message jest po prostu sprawdzanie każdej linii w pliku, aby sprawdzić, czy jest to błąd i zwracanie komunikatu o błędzie.

Plik log.txt jest otwarty, a wszystkie linie w nim są odczytywane na liście. Wtedy pop pierwszy element, który jest nagłówkiem. Następnie przechodzimy przez każdą linię i sprawdź, czy pojawia się komunikat o błędzie. Jeśli istnieje, zwiększymy liczbę dla tego konkretnego komunikatu o błędzie.

Po sprawdzeniu wszystkich linii sortujemy słownik messages, z wyjątkiem tego, że chcemy, aby uzyskać), sortuj go przez wartości słownika, a b) Sortuj go w odwrocie.

Wreszcie wydrukujemy posortowane elementy w kolejności, a liczba razy miała miejsce.

1
Batman 7 lipiec 2017, 03:44

Dla podobnego zadania użyłem kolejnej sztuczki:

fname = "summary.log"
with open(fname) as f:
    content = f.readlines()
content = [x.strip() for x in content]
commits = []

def onHeader(obj):
    date = obj.group(1)
    time = obj.group(2)
    commits.append(CCommitInfo(date, time))

def onFile(obj):
    added = int(obj.group(1))
    removed = int(obj.group(2))
    commits[-1].changed(added, removed)

matchers = []
matchers.append((re.compile(r"(.+?)\s(.+?)\s\+\d+$"), onHeader))
matchers.append((re.compile(r"^(\d+)\t(\d+).+\.(php|pas)"), onFile))

def match(s):
    for x in matchers:
        r = x[0].search(s)
        if r:
            x[1](r)
            break

for x in content:
    match(x)

Przepraszam za kod "jak jest". Jak widać, dodaję do matchers pary REGEXP-Callback i dopasuj je do każdej linii. Prosty i potężny.

1
Green_Wizard 4 lipiec 2017, 18:00