我建议您不要在看到#字符时忽略整行;只忽略行的其余部分。使用名为partition的字符串方法函数可以轻松完成此操作:with open("filename") as f:
for line in f:
line = line.partition('#')[0]
line = line.rstrip()
# ... do something with line ...
partition返回一个元组:分区字符串之前的所有内容、分区字符串以及分区字符串之后的所有内容。因此,通过使用[0]索引,我们只获取分区字符串之前的部分。
编辑:
如果您使用的是没有partition()的Python版本,可以使用以下代码:with open("filename") as f:
for line in f:
line = line.split('#', 1)[0]
line = line.rstrip()
# ... do something with line ...
这将拆分“#”字符上的字符串,然后保留拆分前的所有内容。参数1使.split()方法在一次拆分后停止;因为我们只是获取第0个子字符串(通过使用[0]索引),所以如果不使用参数1,您将得到相同的答案,但这可能会快一点。(由于@gnr的评论,我的原始代码被简化了。我原来的代码没有什么好的理由是更混乱的;谢谢,@gnr.)
您也可以编写自己版本的partition()。这里有一个叫做part():def part(s, s_part):
i0 = s.find(s_part)
i1 = i0 + len(s_part)
return (s[:i0], s[i0:i1], s[i1:])
@dalle注意到“#”可以出现在字符串中。正确处理这个案子不容易,所以我忽略了,但我应该说点什么。
如果你的输入文件有足够简单的规则来引用字符串,这并不难。如果您接受任何合法的Python引号字符串,这将是很困难的,因为有单引号、双引号、多行引号,其中反斜杠转义行尾,三引号字符串(使用单引号或双引号),甚至原始字符串!正确处理这一切的唯一可能方法是一个复杂的状态机。
但是如果我们将自己限制在一个简单的带引号的字符串中,我们就可以用一个简单的状态机来处理它。我们甚至可以在字符串中使用反斜杠双引号。c_backslash = '\\'
c_dquote = '"'
c_comment = '#'
def chop_comment(line):
# a little state machine with two state varaibles:
in_quote = False # whether we are in a quoted string right now
backslash_escape = False # true if we just saw a backslash
for i, ch in enumerate(line):
if not in_quote and ch == c_comment:
# not in a quote, saw a '#', it's a comment. Chop it and return!
return line[:i]
elif backslash_escape:
# we must have just seen a backslash; reset that flag and continue
backslash_escape = False
elif in_quote and ch == c_backslash:
# we are in a quote and we see a backslash; escape next char
backslash_escape = True
elif ch == c_dquote:
in_quote = not in_quote
return line
我真的不想在一个题为“初学者”的问题中把这个复杂化,但是这个状态机相当简单,我希望它会很有趣。