2013-07-22 2 views
3

Я использую python для просмотра файла и удаления любых комментариев. Комментарий определяется как хэш и что-то справа от него. до тех пор, пока хеш не находится внутри двойных кавычек. Я в настоящее время есть решение, но оно кажется неоптимальным: (? Т.е. через регулярные выражения)Удаление хэш-комментариев, которые не входят в кавычки

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" ' 

Edit: Вот чисто регулярное решение, созданное 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), чтобы получить индекс. Он не обрабатывает escape-обратные экраны, если вы хотите, чтобы в строку помещалась цитата с обратным слэшем. не проверяется.

+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) 

Кажется, что нужно работать. Хотя я не уверен, как он может обрабатывать символы новой строки между окнами и linux.

Смежные вопросы