使用python和正则表达式从文本文件中删除行

时间:2014-05-29 18:35:35

标签: python regex

我有一些文本文件,我想删除所有以星号(“*”)开头的行。

制作示例:

words
*remove me
words
words
*remove me 

我当前的代码失败了。它如下:

import re

program = open(program_path, "r")
program_contents = program.readlines()
program.close() 

new_contents = []
pattern = r"[^*.]"
for line in program_contents:
    match = re.findall(pattern, line, re.DOTALL)
    if match.group(0):
        new_contents.append(re.sub(pattern, "", line, re.DOTALL))
    else:
        new_contents.append(line)

print new_contents

这会产生['','''','','' ,'',' ','',' ','&# 39;,' *',''],这不是goo。

我是一个蟒蛇新手,但我渴望学习。我最终会把它捆绑成一个函数(现在我只想在ipython笔记本中找到它)。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

想要使用[^...]否定字符类;您现在正在匹配所有字符,但*.字符除外。

*是一个元字符,您希望将其转义为\*.'匹配任何字符'语法都需要乘数才能匹配多个字符。不要在这里使用re.DOTALL;您是逐行操作但不想删除换行符。

无需先测试;如果没有要替换的东西,则返回原始行。

pattern = r"^\*.*"
for line in program_contents:
    new_contents.append(re.sub(pattern, "", line))

演示:

>>> import re
>>> program_contents = '''\
... words
... *remove me
... words
... words
... *remove me 
... '''.splitlines(True)
>>> new_contents = []
>>> pattern = r"^\*.*"
>>> for line in program_contents:
...     new_contents.append(re.sub(pattern, "", line))
... 
>>> new_contents
['words\n', '\n', 'words\n', 'words\n', '\n']

答案 1 :(得分:1)

您的正则表达式似乎不正确:

[^*.]

表示匹配任何非^*.的字符。在括号表达式中,第一个^之后的所有内容都被视为文字字符。这意味着在表达式中.匹配。字符,而不是通配符。

这就是为"*"开头*行的原因,你要替换除*之外的所有字符!您还可以在原始字符串中保留任何.。由于其他行不包含*.,因此所有字符都将被替换。

如果您想匹配以*开头的行:

^\*.*

可能更容易的是这样的事情:

pat = re.compile("^[^*]")

for line in contents:
    if re.search(pat, line):
        new_contents.append(line)

此代码只保留不以*开头的任何行。

在模式^[^*]中,第一个^匹配字符串的开头。表达式[^*]匹配除*之外的任何字符。因此,此模式一起匹配不是*的字符串的任何起始字符。

使用正则表达式时,真正考虑这是一个很好的技巧。您是否只需要断言字符串,是否需要更改或删除字符串中的字符,是否需要匹配子字符串?

就python而言,你需要考虑每个函数给你的内容以及你需要做些什么。有时候,就像在我的例子中,你只需要知道找到了一个匹配。有时您可能需要对匹配做一些事情。

有时re.sub不是最快或最好的方法。当你可以完全跳过这一行时,为什么还要费心去掉每一行并替换所有的字符呢?在过滤时,制作一个空字符串是没有意义的。

最重要的是:我真的需要正则表达式吗? (在这里你没有!)

这里你真的不需要正则表达式。由于您知道分隔符的大小和位置,因此可以像这样检查:

if line[0] != "*": 

这比正则表达式更快。它们是非常强大的工具,可以很好地解决问题,但对于具有固定宽度和位置的分隔符,您并不真正需要它们。正则表达式比使用此信息的方法昂贵得多。

答案 2 :(得分:0)

你可以这样做:

print '\n'.join(re.findall(r'^[^*].*$', ''.join(f), re.M))

示例:

txt='''\
words
*remove me
words
words
*remove me '''

import StringIO

f=StringIO.StringIO(txt)

import re

print '\n'.join(re.findall(r'^[^*].*$', ''.join(f), re.M))