删除不在引号内的哈希注释
Posted
技术标签:
【中文标题】删除不在引号内的哈希注释【英文标题】:Removing hash comments that are not inside quotes 【发布时间】:2013-07-21 09:33:57 【问题描述】:我正在使用 python 浏览文件并删除所有 cmets。注释被定义为散列和它右侧的任何内容只要散列不在双引号内。我目前有一个解决方案,但似乎不是最理想的:
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)])
【问题讨论】:
【参考方案1】: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)
获取索引。如果您希望能够将反斜杠转义的引号放在字符串中,它不处理反斜杠转义。这是未经测试的。
【讨论】:
这真的很聪明,我知道这样的事情是可能的,我只是不知道该怎么做。谢谢,工作就像一个魅力。 单行,方便复制意大利面:re.search(r'(?:"[^"]*"|[^"#])*(#)', your_string) 【参考方案2】:您可以使用此脚本删除 cmets:
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.
【讨论】:
这是第一个对我有用的答案!.. 但它不适用于单引号内的 cmets。 @AmanDeep:编辑模式以使其也适用于单引号并不难。 我尝试将新模式放在 () 组中,由 | 分隔.....但它不会工作 r'(?s)("[^"\]*(?:\\.[^"\]*)*")|#[^\n]*|((? s)('[^'\]*(?:\\.[^'\]*)*')|#[^\n]*)'【参考方案3】:这段代码太丑了,我不得不贴出来。
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 之间的换行符。
【讨论】:
以上是关于删除不在引号内的哈希注释的主要内容,如果未能解决你的问题,请参考以下文章