2016-07-12 2 views
0

저는 파이썬을 처음 사용하고 로그 파일을 분석하는 데 어려움이 있습니다. 제가 가장 Pythonic 방식으로 아래에서 어떻게 성취 할 수 있는지 이해해 주시겠습니까?파이썬에서 텍스트 서식 변경

----- Log Entry 5 ----- 
Time  : 2016-07-12 09:00:00 
Animal  : Brown Bear 
Bird  : White Owl 
Fish  : Salmon 


----- Log Entry 6 ----- 
Time  : 2016-07-12 09:00:00 
Animal  : Brown Bear 
Bird  : Parrot 
Fish  : Tuna 


----- Log Entry 7 ----- 
Time  : 2016-07-12 09:00:00 
Animal  : Lion 
Bird  : White Owl 
Fish  : Sword Fish 


----- Log Entry 8 ----- 
Time  : 2016-07-12 09:15:00 
Animal  : Lion 
Bird  : White Owl 
Fish  : Sword Fish 

원하는 출력 1 : 나는 아래처럼 보이게 로그를 다시 포맷하고 싶습니다 :

Time: 2016-07-12 09:00:00 Animal: Brown Bear Bird: White Owl Fish : Salmon 
Time: 2016-07-12 09:00:00 Animal: Brown Bear Bird: Parrot  Fish : Tuna 
Time: 2016-07-12 09:00:00 Animal: Lion  Bird: White Owl Fish : Sword Fish 
Time: 2016-07-12 09:15:00 Animal: Lion  Bird: White Owl Fish : Sword Fish 

원하는 출력 2 : 그럼 타임 스탬프를 조회하고 얻을 수있는 능력을 가지고 싶습니다 카운트 요약 :

Time: 2016-07-12 09:00:00 
Name:  Count: 
Brown Bear 2 
Lion  1 
White Owl 2 
Parrot  1 
Salmon  1 
Tuna  1 
Sword Fish 1 

Time: 2016-07-12 09:15:00 
Name:  Count: 
Lion  1 
White Owl 1 
Sword Fish 1 

내 코드 지금까지 :

import os, sys, time, re, collections, subprocess 

show_cmd = 'cat question | egrep -v \'^$|=|Log\' | awk \'ORS=NR%4?FS:RS\' | grep Time' 
log = (subprocess.check_output(show_cmd, shell=True).decode('utf-8')) 

def time_field(): 
    logRegex = re.compile(r'Time\s*:.*\d\d\d-\d\d-\d\d\s\d\d:\d\d') 
    log_parsed = (logRegex.findall(log)) 
    a = (str(log_parsed).replace(' ', '')) 
    a = ((' ' + a[1:-1]).split(',')) 
    for i in a: 
     print(i) 

time_field() 
+4

지금까지 해보신 것은 무엇입니까? 현재 구현할 때 어떤 어려움을 겪고 있습니까? 최신 코드 시도 [mcve]를 제공해 주시겠습니까? – idjaw

+0

어떤 방식 으로든 파일을 읽을 수 있었습니까? – depperm

+0

은 예상 출력을 보여 주거나 데이터 형식에서 미러링해야하는 대상입니까? – patrick

답변

1

이렇게하는 방법에는 여러 가지가 있습니다. 개인적으로 아마 정규 표현식이 더 효율적이지 않을 것이고 표현식이 복잡하고 융통성이 없기 때문에 정규 표현식 사용을 피할 것입니다. 여기에 내가 생각 해낸 뭔가 :

class Entry: 
    def __init__(self): 
     self.time = None 
     self.animal = None 
     self.bird = None 
     self.fish = None 

    def __repr__(self): 
     fmt = "{0} {1} {2} {3}".format(
      "Time: {time: <{width}}", 
      "Animal: {animal: <{width}}", 
      "Bird: {bird: <{width}}", 
      "Fish: {fish: <{width}}") 
     return fmt.format(
      time=self.time, animal=self.animal, 
      bird=self.bird, fish=self.fish, 
      width=12) 

    def __radd__(self, other): 
      return self.__add__(other) 

    def __add__(self, other): 
     if type(other) == dict: 
      for i in [self.animal, self.bird, self.fish]: 
       if i in other: other[i] += 1 
       else: other[i] = 1 
      return other 
     elif type(other) == Entry: 
      return self.__add__({}) + other 
     else: 
      return self.__add__({}) 

def parse_log(path): 
    def extract(line): 
     start = line.find(':') + 1 
     return line[start:].strip() 

    entries = [] 
    entry = None 
    with open(path, 'r') as f: 
     for line in f.readlines(): 
      if line.startswith('-----'): 
       if entry: entries.append(entry) 
       entry = Entry() 
      elif line.startswith('Time'): 
       entry.time = extract(line) 
      elif line.startswith('Animal'): 
       entry.animal = extract(line) 
      elif line.startswith('Bird'): 
       entry.bird = extract(line) 
      elif line.startswith('Fish'): 
       entry.fish = extract(line) 

     if entry: entries.append(entry) 

    return entries 


def print_output_1(entries): 
    for entry in entries: 
     print entry 

def print_output_2(entries, time): 
    animals = sum([e for e in entries if e.time == time]) 

    print "Time: {0}".format(time) 
    print "Name:  Count:" 
    for animal, count in animals.items(): 
     print "{animal: <{width}} {count}".format(
       animal=animal, count=count, width=12) 


logPath = 'log.log' 
time = '2016-07-12 09:15:00' 
entries = parse_log(logPath) 

print_output_1(entries) 
print "" 
print_output_2(entries, time) 

출력은 (log.log 일치 당신이 준 입력이 주어진) :이 코드가 작동

Time: 2016-07-12 09:00:00 Animal: Brown Bear Bird: White Owl Fish: Salmon 
Time: 2016-07-12 09:00:00 Animal: Brown Bear Bird: Parrot  Fish: Tuna 
Time: 2016-07-12 09:00:00 Animal: Lion   Bird: White Owl Fish: Sword Fish 
Time: 2016-07-12 09:15:00 Animal: Lion   Bird: White Owl Fish: Sword Fish 

Time: 2016-07-12 09:15:00 
Name:  Count: 
White Owl 1 
Sword Fish 1 
Lion   1 

방법은 우리의 장점에 객체 지향 프로그래밍을 사용하는 것입니다 로그 항목을 저장하고 특정 형식으로 로그 항목을 표시하며 특정 속성에 따라 로그 항목을 결합해야하는 작업을 단순화하기 위해 우선

Entry 객체와 속성 (self.time, self.animal, self.bird, self.fish)은 로그 엔트리를 나타내고 있습니다. 속성에 저장된 정보가 정확하다고 가정하면 해당 정보를 형식이 지정된 문자열로 나타내는 메서드를 만들 수 있습니다. 메서드 __repr__()은 파이썬이 객체의 문자열 표현을 원할 때 호출되므로이 코드를 삽입하는 것이 좋습니다. 이 메서드에서는 format 함수를 많이 사용하지만, format에있는 python 설명서를 탐색 한 후 어떻게 작동하는지 분명해야합니다.

지정한 두 번째 출력을 얻으려면 이러한 입력 개체를 결합하는 방법이 필요합니다. 이것은 여러 가지 방법으로 할 수 있으며 내가 한 방식대로 반드시 최선은 아닙니다. 나는 + 연산자가 객체에서 사용될 때 호출되는 __radd__()__add__() 메쏘드를 사용했다. 이렇게하면 코드 entry1 + entry2 또는 sum([entry1, entry2])을 사용하여 두 항목의 동물 합계를 얻을 수 있습니다. 그러나 임의의 정보를 포함 할 수 없기 때문에 Entry 클래스는 합계 결과를 저장하는 데 사용할 수 없습니다. 대신 dict 개체를 사용하여 두 개의 Entry 개체를 합산 한 결과로 선택했습니다. 두 개 이상의 개체를 합치려면 EntryEntry은 개체와 합계 할 수 있어야합니다. Entry + Entry + Entry 결과는 dict + Entry이됩니다.

__add__() 함수는 추가 할 개체가 dict 개체인지 확인합니다. 이 경우 항목의 각 동물이 dict에 이미 있는지 확인합니다. 그렇지 않다면 동물을 열쇠로 추가 할 것입니다. 그렇지 않으면 해당 키의 값이 증가합니다. __radd__()은 특별한 경우에 사용된다는 점을 제외하고는 __add__()과 유사합니다. 자세한 내용은 python 설명서를 참조하십시오.

객체가 Entry 인 경우를 들어

이 코드는 각 Entry 개체에서 모든 동물을 수집하고 그 정보에서 dict을 만들기 위해 작성되었습니다 수 있지만, 코드가 이미 존재하기 때문에 dict와 함께 Entry을 추가 하나의 객체를 빈 dict에 추가 한 다음 결과물 인 dict을 다른 Entry 객체와 함께 추가하는 것이 더 쉽습니다.

다른 모든 개체의 경우 Entrydict 자체 또는 자체가 빈 dict으로 추가 된 설명을 반환합니다.

이제는 앞에서 설명한 목표를 달성하기위한 모든 도구가 있습니다. 원하는 출력 1과 일치하는 Entry의 문자열 표현을 얻으려면 print entry 또는 strrepr = str(entry)이 필요합니다. 원하는 출력 2를 얻으려면 좀 더 많은 작업이 필요하지만 단순히 동일한 self.time 속성을 가진 모든 항목을 합친 다음 결과 dict를 표시하는 것입니다.

코드의 마지막 부분은 로그를 구문 분석하여 Entry 개체 목록을 만드는 것입니다. 이 코드는 로그를 통해 줄 단위로 걸어서 Entry 정보로 채 웁니다. 나는 이것이 매우 직관적이라고 생각하지만 이해가되지 않는다면 자유롭게 질문 할 수 있습니다.

+0

이것은 내가 원하는 것을 정확히 완성했습니다! 솔직히 말해서 나는 당신의 방법을 시도하고 이해하기 위해 심각한 시간을 할애 할 필요가 있습니다. 저는 파이썬에서 초보자입니다. 그러나이 형식으로 많은 로그를 다루기 때문에 이것은 나에게 훌륭한 참고 자료입니다. 신속한 회신과 지원에 감사드립니다! – MBasith

+0

나는 코드를 더 명확하게 설명하는 설명을 추가했다. 이 답변이 귀하의 필요를 충족 시키면 정확한 것으로 표시하십시오. – Alden

+0

설명에 감사하는 Alden. 그것은 매우 도움이되었다! – MBasith