表达式直到注释或行尾

3 投票
4 回答
14028 浏览
提问于 2025-04-15 11:57

虽然这个问题和这个讨论有点相似,但我觉得我在用正则表达式写代码的时候可能做错了什么。

我想要匹配一行中的所有内容,直到遇到注释符号(“#”)或者行的结束(如果没有注释的话)。

我现在用的正则表达式是:(.*)(#|$)

(.*) = 所有内容
(#|$) = 注释或者行的结束

代码如下:

OPTION = re.compile(r'(?P<value>.*)(#|$)')
file = open('file.txt')
lines = file.read()
for line in lines.split('\n'):
    get_match = OPTION.match(line)
    if get_match:
        line_value = get_match.group('value')
        print "Match=  %s" % line_value

这个正则表达式可以工作,但它并没有去掉注释。如果文件中有一行像这样:

this is a line   # and this is a comment

运行代码时,我仍然会得到整行内容。

我是不是在正则表达式中漏掉了什么值或信息,还是说我需要对代码进行修改?

4 个回答

1

@Can、@Benji 和 @ΤΖΩΤΖΙΟΥ 提供了三个很棒的解决方案,看看它们的匹配速度也是很有趣的(这就是 timeit 的用途——进行一些无意义的小测试,哈哈;)。比如:

$ python -mtimeit -s'import re; r=re.compile(r"([^#]*)(#.*)?"); s="this is a line   # and this is a comment"' 'm=r.match(s); g=m.group(1)'
100000 loops, best of 3: 2.02 usec per loop

对比

$ python -mtimeit -s'import re; r=re.compile(r"^(.*?)(?:#|$)"); s="this is a line   # and this is a comment"' 'm=r.match(s); g=m.group(1)'
100000 loops, best of 3: 4.19 usec per loop

对比

$ python -mtimeit -s'import re; r=re.compile(r"(.*?)(#|$)"); s="this is a line   # and this is a comment"' 'm=r.match(s); g=m.group(1)'
100000 loops, best of 3: 4.37 usec per loop

最后的赢家是……几种模式的结合!-)

$ python -mtimeit -s'import re; r=re.compile(r"(.*?)(#.*)?"); s="this is a line   # and this is a comment"' 'm=r.match(s); g=m.group(1)'
1000000 loops, best of 3: 1.73 usec per loop

声明:当然,如果这是一个真正的性能测试,速度确实很重要的话,应该用很多不同的、相关的值来测试 s,而且测试的内容也要超出这种小测试等等。但我还是觉得 timeit 是个无穷无尽的乐趣来源!-)

3

这是一个正确的正则表达式,可以用来做类似的事情:

([^#]*)(#.*)?

另外,为什么不直接使用

file = open('file.txt')
for line in file:
7

这个 * 符号是贪婪的,也就是说它会尽可能多地匹配字符串,所以它把整行都匹配了,包括 # 后面的内容,一直到行的结尾。你只需要把 ".*" 改成 ".*?",这样就能正常工作了。

想了解更多信息,可以查看这个 正则表达式入门指南

撰写回答