2017-04-27 6 views
0

저는 지난 8 개월 동안 파이썬으로 만 프로그래밍 했으므로, 아마 파이썬에 대한 noob 접근 방식을 생각해보십시오.파일에서 특정 긴 줄의 텍스트를 제거합니다.

내 문제는 다음과 같습니다. 누군가가 나를 도와 줄 수 있기를 바랍니다.

는이 같은 인스턴스 뭔가 (그냥 싹둑)를 들어, 파일에 데이터를 많이 가지고 :

SWITCH MGMT IP;SWITCH HOSTNAME;SWITCH MODEL;SWITCH SERIAL;SWITCH UPTIME;PORTS NOT IN USE 
10.255.240.1;641_HX_3560X;WS-C3560X-24P-S;FDO1601V031;12 weeks, 3 days, 23 hours, 33 minutes;1 
10.255.240.7;641_HX_LEFT_2960x;WS-C2960X-24PS-L;FOC1750S2E5;12 weeks, 4 days, 7 minutes;21 
10.255.240.8;641_UX_BASEMENT_2960x;WS-C2960X-24PS-L;FOC1750S2AG;12 weeks, 4 days, 7 minutes;12 
10.255.240.9;641_UX_SPECIAL_2960x;WS-C2960X-24PS-L;FOC1750S27M;12 weeks, 4 days, 8 minutes;25 
10.255.240.2;641_UX_OFFICE_3560;WS-C3560-8PC-S;FOC1202U24E;2 years, 30 weeks, 3 days, 16 hours, 43 minutes;2 
10.255.240.3;641_UX_SFO_2960x;WS-C2960X-24PS-L;FOC1750S2BR;12 weeks, 4 days, 7 minutes;14 
10.255.240.65;641_HX_3560X;WS-C3560X-24P-S;FDO1601V031;12 weeks, 3 days, 23 hours, 34 minutes;1 
10.255.240.5;641_HX_RIGHT_2960s;WS-C2960S-24PS-L;FOC1627X1BF;12 weeks, 4 days, 12 minutes;16 
10.255.240.6;641_HX_LEFT_2960x-02;WS-C2960X-24PS-L;FOC1750S2C4;12 weeks, 4 days, 7 minutes;15 
10.255.240.4;641_UX_BASEMENT_2960s;WS-C2960S-24PS-L;FOC1607Z27T;12 weeks, 4 days, 8 minutes;3 
10.255.240.62;641_UX_OFFICE_3560CG;WS-C3560CG-8PC-S;FOC1646Y0U2;15 weeks, 5 days, 12 hours, 15 minutes;6 

나는 일련 번호가 더 발생하면 파일의 모든 데이터를 실행하고 확인하려면 한번 이상. 그것이 발견되면 중복을 제거하고 싶습니다. 결과에 동일한 스위치 또는 라우터가 여러 번 포함될 수있는 이유는 관리 할 수있는 여러 개의 레이어 3 인터페이스가있을 수 있기 때문입니다.

위의 예에서 그렇습니다. 데이터를 살펴본 후에는 다음 줄을 제거해야합니다.

10.255.240.65;641_HX_3560X;WS-C3560X-24P-S;FDO1601V031;12 weeks, 3 days, 23 hours, 34 minutes;1 

파일의 두 번째 줄에 이미 동일한 스위치와 일련 번호가 포함되어 있습니다.

나는 이것을 알아 내기 위해 며칠을 보냈다. 어떻게 달성 할 수 있었는지, 두통을주기 시작했다.

내 기본 코드는 다음과 같습니다

if os.stat("output.txt").st_size != 0: 
    with open('output.txt','r') as file: 
     header_line = next(file) # Start from line 2 in the file. 

    data = [] # Contains the data from the file. 
    sn = [] # Contains the serial numbers to check up against. 
    ok = [] # Will contain the clean data with no duplicates. 

    data.append(header_line.split(";")) # Write the head to data. 

    for line in file: # Run through the file data line for line. 
     serialchk = line.split(";") # Split the data into a list 
     data.append(serialchk) # Write the data to data list. 
     sn.append(serialchk[3]) # Write the serial number to sn list. 

end = len(data) # Save the length of the data list, so i can run through the data 
i = 0 # For my while loop, so i know when to stop.' 

while i != end: # from here on out i am pretty lost on how to achieve my goal. 
     found = 0 
     for x in range(len(data)): 
      if sn[i] == data[x][3]: 
       found += 1 
       print data[x] 
       ok.append(data[x]) 
      elif found > 1: 
       print "Removing:\r\n" 
       print data[x-1] 
       del ok[-1] 
       found = 0 
     i += 1 

이 할 수있는 더 파이썬 방법이 있나요? 나는 모든 재능있는 사람들과 여기서 확신 할 수있다. 누군가가 나에게 이런 일이 일어나는 방법에 대한 단서를 줄 수있다.

대단히 감사합니다.

+0

먼저 [csv 모듈] (https://docs.python.org/3/library/csv.html)을 확인해 보겠습니다. – Kendas

답변

0

나의 제안 :

if os.stat("output.txt").st_size != 0: 
    with open('output.txt','r') as file: 
     header_line = next(file) # Start from line 2 in the file. 

    srn = set() # create a set where the seen srn will be stored 
    ok = [] # Will contain the clean data with no duplicates. 

    ok.append(header_line.split(";")) # Write the head to ok. 

    for line in file: # Run through the file data line for line. 
     serialchk = line.split(";") # Split the data into a list 
     if serialchk[3] not in srn: # if the srn hasn't be seen 
      ok.append(serialchk) # add the row to ok 
      srn.add(serialchk[3]) # add the srn to seen set 
     else: # if the srn has already be seen 
      print "Removing: "+";".join(serialchk) # notify the user it has been skipped 

당신은 확인이 UNIQ의 SRN 만 행을 포함하여 결국, 삭제 된 행 를 인쇄 할 수 있습니다 당신은이 방법이 더 복잡하게 만들고있어

+0

중복 제거 된 줄을 메모리에 저장할 때 왜 저장해야하는지 직접 파일? –

+1

아무데도 지정되지 않았으므로 @Cown이 결국 파일에 쓰려고했습니다. – Trolldejo

+1

Duh! 네, 실제로 - 논평하기 전에 두 번 읽었어야합니다 (그리고 아마도 다른 커피 xD를 가져와야 할 것입니다). –

1

희망이 도움이 될 수 있습니다 (메모리에 전체 파일을로드하여 중복 된 파일을 필터링하지 않아도됩니다.)

간단한 방법은 파일을 한 줄씩 읽고 각 줄마다 일련 번호가 이미 있는지 확인하는 것입니다. 네, 선을 건너 뛰면 다른 일련 번호를 저장하고 출력 파일에 줄을 쓰기 :

seen = set() 
with open('output.txt','r') as source, open("cleaned.txt", "w") as dest: 
    dest.write(next(source)) # Start from line 2 in the file. 
    for line in src: 
     sn = line.split(";")[3] 
     if sn not in seen: 
      seen.add(sn) 
      dest.write(line) 
     # else, well we just ignore the line ;) 

NB를 : 당신이 파일에 중복 제거 된 줄을 다시 작성하려는 가정합니다. 알고리즘을 메모리에 유지하려면 알고리즘은 거의 동일하지만 대신 deduplicated 행을 list에 추가하십시오. 그러나 거대한 파일이있는 경우 메모리 사용에주의하십시오.

+0

고맙습니다. 파이썬에서 jedimaster에 대한 단어가 있다면, 나는 당신이 하나라는 것을 확신합니다. 귀하의 예제는 당신이 진술 한대로 거의 메모리를 사용하지 않으며 스크립트는 더 빨리 실행됩니다. 어쩌면 당신은 파이썬 신입니까? 흠. – Cown

+0

@Cown 이것은 파이썬 기술과 실제로는 거의 관계가 없으며, 단순한 기본적인 알고리즘입니다. –

+0

나는 알고리듬이 그리 좋지 않다고 생각한다.하지만 이봐, 우리 모두는 어떻게 든 배워야한다. 비록 당신이하는 것처럼 파이썬을 보는 것이 좋을 것입니다. :-) – Cown

-1

변경 사항을 안내해 드리겠습니다.

내가 할 첫 번째 일은 csv 모듈을 사용하여 입력을 구문 분석하는 것입니다. DictReader을 반복 할 수 있으므로 간결하게하기 위해 선택합니다. listdata에는 최종 (정리 된) 결과가 포함됩니다.

from csv import DictReader 
import os 

if os.stat("output.txt").st_size != 0: 
    with open('output.txt', 'r') as f: 
     reader = DictReader(f, delimiter=';') # create the reader instance 

     serial_numbers = set() 
     data = [] 
     for row in reader: 
      if row["SWITCH HOSTNAME"] in serial_numbers: 
       pass 
      else: 
       data.append(row) 
       serial_numbers.add(row["SWITCH HOSTNAME"]) 

데이터의 형식은 listdict의의에 list s의 list에서, 내 방식에 의해 변경,하지만 것이다 당신은 새로운 CSV 파일로 DictWriter 클래스를 청소 한 데이터를 저장하려는 경우 그렇게하는 쉬운 방법이어야합니다.

+0

안녕하세요, 왜 내 데이터가 CSV 파일이라고 생각하는지 잘 모르겠습니다. 그렇지 않습니다. 그것은 평범한 텍스트 데이터로, 스위치에서 실행 및 로깅으로 추출한 것입니다. 예를 들어 Excel로 가져 오기가 더 쉽도록 세미콜론으로 구분됩니다. 위의 예를 주셔서 감사하지만 그것은 내가 찾고있는 것이 아닙니다. :-) – Cown

+0

csv는 '쉼표로 구분 된 값'을 의미합니다. 기술적으로 값은 세미콜론으로 구분되지만 형식은 동일합니다. 첫 번째 행은 구분 기호 ('; ')로 구분 된 값의 머리글을 포함하고, 후속 행은 구분 기호로 분리 된 데이터 값을 포함합니다. Wikipedia에서 마지막 [예제] (https://en.wikipedia.org/wiki/Comma-separated_values#Example)를 확인하십시오. – Kendas