删除不在引号内的哈希注释

时间:2013-07-22 15:12:29

标签: python regex comments quotes strip

我正在使用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)

有没有办法在没有for循环的情况下找到不在引号内的第一个散列(即通过正则表达式?)

示例:

' "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代码版本。此代码还通过包含对字符串结尾($)的检查来消除'if':

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

3 个答案:

答案 0 :(得分:3)

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)来获取索引。如果您希望能够在字符串中放入反斜杠转义引号,则它不会处理反斜杠转义。这是未经测试的。

答案 1 :(得分: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.

答案 2 :(得分: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)

似乎工作。虽然我不确定它如何处理windows和linux之间的换行符。