2013-07-22 2 views
3

저는 파이썬을 사용하여 파일을 검토하고 주석을 제거합니다. 해시가 이중 따옴표 안에 있지 않는 한 주석은 해시로 정의되며 그 오른쪽에있는 모든 것 . 나는 현재 해결책을 가지고 있지만 차선 것 같다 (? 즉, 정규 표현식을 통해)따옴표 안에없는 해시 주석 제거

filelines = [] 
    r = re.compile('(".*?")') 
    for line in f: 
     m = r.split(line) 
     nline = '' 
     for token in m: 
      if token.find('#') != -1 and token[0] != '"': 
       nline += token[:token.find('#')] 
       break 
      else: 
       nline += token 
     filelines.append(nline) 

하지 따옴표 안에없이 루프에 대한 첫 번째 해시를 찾을 수있는 방법이 있나요

예를 :

' "Phone #":"555-1234" ' -> ' "Phone #":"555-1234" ' 
' "Phone "#:"555-1234" ' -> ' "Phone "' 
'#"Phone #":"555-1234" ' -> '' 
' "Phone #":"555-1234" #Comment' -> ' "Phone #":"555-1234" ' 

편집 : 여기 user2357112 만든 순수 정규식 솔루션입니다. 나는 그것을 테스트하고 훌륭하게 작동합니다 :

filelines = [] 
r = re.compile('(?:"[^"]*"|[^"#])*(#)') 
for line in f: 
    m = r.match(line) 
    if m != None: 
     filelines.append(line[:m.start(1)]) 
    else: 
     filelines.append(line) 

이 정규식이 어떻게 작동하는지에 대한 자세한 내용은 회신을 참조하십시오.

Edit2가이 :. 여기에 내가 이스케이프 문자 (\ ")을 설명하기 위해 수정 user2357112의 코드 버전의이 코드는 없애는 '의 경우'문자열 ($)의 끝 부분에 대한 검사를 포함하여 :

filelines = [] 
r = re.compile(r'(?:"(?:[^"\\]|\\.)*"|[^"#])*(#|$)') 
for line in f: 
    m = r.match(line) 
    filelines.append(line[:m.start(1)]) 

답변

2
r'''(?:  # Non-capturing group 
     "[^"]*" # A quote, followed by not-quotes, followed by a quote 
     |  # or 
     [^"#] # not a quote or a hash 
    )   # end group 
    *   # Match quoted strings and not-quote-not-hash characters until... 
    (#)  # the comment begins! 
''' 

이것은 한 줄로 작동하도록 설계된 자세한 정규 표현식이므로 re.VERBOSE 플래그를 사용하고 한 번에 한 줄씩 입력하십시오. 첫 번째 따옴표가없는 해시가 있으면 그룹 1로 캡처됩니다. 하나이므로 인덱스를 얻기 위해 match.start(1)을 사용할 수 있습니다. 역 슬래시 이스케이프 된 따옴표를 문자열에 넣을 수 있도록하려면 백 슬래시 이스케이프를 처리하지 않습니다. 안된다.

+0

그건 정말 영리한 일입니다. 그런 일이 가능하다는 것을 알았습니다. 어떻게해야할지 모르겠습니다. 감사합니다, 매력처럼 일했습니다. – RPGillespie

+0

한 줄에 파스타를 쉽게 복사 할 수 있습니다. re.search (r '(? : "[^"# *) | * (#)', your_string) – Yourpalal

0

당신이 스크립트를 사용하여 주석을 제거 할 수 있습니다

import re 
print re.sub(r'("(?:[^"]+|(?<=\\)")*")|#[^\n]*', lambda m: m.group(1) or '', '"Phone #"#:"555-1234"') 
아이디어는 큰 따옴표로 일부를 캡처하고 날카로운 검색하기 전에 자체를 교체하는 것입니다

:

(    # open the capture group 1 
    "    # " 
    (?:   # open a non-capturing group 
     [^"]+  # all characters except " 
     |   # OR 
     (?<=\\)" # escaped quote 
    )*   # repeat zero or more times 
    "    # " 
)     # close the capture group 1 

|     # OR 

#[^\n]*   # a sharp and zero or one characters that are not a newline. 
0

이 코드를 너무 추해서, 나는 그것을 게시해야했다.

def remove_comments(text): 
    char_list = list(text) 
    in_str = False 
    deleting = False 
    for i, c in enumerate(char_list): 
     if deleting: 
      if c == '\n': 
       deleting = False 
      else: 
       char_list[i] = None 
     elif c == '"': 
      in_str = not in_str 
     elif c == '#': 
      if not in_str: 
       deleting = True 
       char_list[i] = None 
    char_list = filter(lambda x: x is not None, char_list) 
    return ''.join(char_list) 

그래도 작동하는 것 같습니다. 비록 그것이 어떻게 윈도우와 리눅스 사이에서 개행 문자를 처리할지 모르겠지만.