移除不在引号内的哈希评论

问题描述 投票:5回答: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)

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

举例说明。

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

编辑:这里是用户2357112创建的一个纯regex解决方案。我测试了一下,效果很好。

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)

更多关于这个regex工作原理的细节请看他的回复。

编辑2: 这里是用户2357112的代码,我修改了它来考虑转义字符(\")。这段代码通过检查字符串的结尾($)来消除 "if"。

filelines = []
r = re.compile(r'(?:"(?:[^"\\]|\\.)*"|[^"#])*(#|$)')
for line in f:
    m = r.match(line)
    filelines.append(line[:m.start(1)])
python regex comments quotes strip
3个回答
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!
'''

这是一个冗长的regex,设计为单行操作,所以一定要使用 re.VERBOSE 标志,并一次只输入一行。如果有的话,它将捕获第一个未引用的哈希作为第1组,所以你可以使用 match.start(1) 来获取索引。它不处理反斜杠转义,如果你想在字符串中加入一个反斜杠转义的引号。这一点还没有测试过。


1
投票

你可以用这个脚本删除注释。

import re
print re.sub(r'(?s)("[^"\\]*(?:\\.[^"\\]*)*")|#[^\n]*', lambda m: m.group(1) or '', '"Phone #"#:"555-1234"')

我们的想法是捕捉双引号中的第一部分 然后在搜索一个尖锐的引号之前用它们自己来替换:

(?s)              # the dot matches newlines too
(                 # open the capture group 1
    "             # "
    [^"\\]*       # all characters except a quote or a backslash
                  # zero or more times
    (?:           # open a non-capturing group
        \\.       # a backslash and any character
        [^"\\]*   # 
    )*            # 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)

不过似乎还能用。虽然我不确定它如何处理windows和linux之间的换行符。

© www.soinside.com 2019 - 2024. All rights reserved.