读取文件时将多个换行符替换为单个换行符

21

我有下面的代码,它从多个文件中读取数据,解析得到的行,并打印结果:

import os
import re

files=[]
pars=[]

for i in os.listdir('path_to_dir_with_files'):
    files.append(i)

for f in files:
    with open('path_to_dir_with_files'+str(f), 'r') as a:
       pars.append(re.sub('someword=|\,.*|\#.*','',a.read()))

for k in pars:
   print k

但是我在输出中遇到了多个换行符的问题:

test1


test2

我希望获得下一个结果,而不是输出中有空行:

 test1
 test2

等等等等。

我尝试使用正则表达式进行操作:

pars.append(re.sub('someword=|\,.*|\#.*|^\n$','',a.read()))

但是它不起作用。我也尝试了使用strip()、rstrip()和replace,但都不起作用。

5个回答

24
你可以使用第二个正则表达式将多个换行符替换为一个换行符,并使用strip函数去掉最后一个换行符。
你可以使用第二个正则表达式将多个换行符替换为一个换行符,并使用strip函数去掉最后一个换行符。
import os
import re

files=[]
pars=[]

for i in os.listdir('path_to_dir_with_files'):
    files.append(i)

for f in files:
    with open('path_to_dir_with_files/'+str(f), 'r') as a:
        word = re.sub(r'someword=|\,.*|\#.*','', a.read())
        word = re.sub(r'\n+', '\n', word).strip()
        pars.append(word)

for k in pars:
   print k

你能逐行而非按文件处理吗?比如用 for line in f: 这样的方式。你能解释一下 re.sub 是什么意思吗?逗号和井号被转义了,我不理解 someword= 的含义。在示例中没有等号。 - Timo
1
当然你可以逐行处理,但在这种情况下f是文件名而不是内容。re.sub会将与第一个参数匹配的内容替换为第二个参数中的内容。请查看文档并尝试一下。 - Kris

2

只是一个简单的例子,但可能不够高效。

entire_file = "whatever\nmay\n\n\n\nhappen"

while '\n\n' in entire_file:
    entire_file = entire_file.replace("\n\n", "\n")

print(entire_file)

你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
这里有一个 bug。它只是将 \n 对半分开。它将每个双重的 \n\n 都替换为一个 \n。因此,如果有 4 个 \n\n\n\n,则现在会变成 2 个 \n\n。 - jth_92

2

不需要修改太多代码,一种简单的方法就是在打印之前检查该行是否为空,例如:

import os
import re

files=[]
pars=[]

for i in os.listdir('path_to_dir_with_files'):
    files.append(i)

for f in files:
    with open('path_to_dir_with_files'+str(f), 'r') as a:
        pars.append(re.sub('someword=|\,.*|\#.*','',a.read()))

for k in pars:
    if not k.strip() == "":
        print k

***编辑 由于pars中的每个元素实际上是文件的整个内容(而不仅仅是一行),因此您需要遍历并替换任何双端行,最简单的方法是使用re。

import os
import re

files=[]
pars=[]

for i in os.listdir('path_to_dir_with_files'):
    files.append(i)

for f in files:
    with open('path_to_dir_with_files'+str(f), 'r') as a:
        pars.append(re.sub('someword=|\,.*|\#.*','',a.read()))

for k in pars:
    k = re.sub(r"\n+", "\n", k)
    if not k.strip() == "":
        print k

请注意,此方法无法处理文件以换行符结尾且下一个文件以换行符开头的情况 - 如果您担心这种情况,您需要添加额外的逻辑来处理它或更改读取数据的方式。

1
或者只是 if k.strip() - Patrick Haugh
这也应该在向pars添加时完成,而不是在迭代pars时完成。 - vallentin
不幸的是,它没有给出适当的结果。如果不是 k.strip() == "",我仍然会得到多个空行。如果只显示列表而不进行迭代,我会得到:test1[]\n\n\n test2\n test5\ntest7[]\ntest[*]\n 等等... - user54
哦,我明白了,因为你只是将整行读入pars中的每个项,所以它不会逐行打印。我修改了我的答案,它只是使用正则表达式来遍历并去除任何重复的\n,并用一个单独的\n替换。 - Kewl

0
使用前瞻正则表达式查找所有的双回车符号r'\n(?=\n),并将其替换为空。这将一次性找到并替换所有这些情况。
import re

files=[]
pars=[]

for i in os.listdir('path_to_dir_with_files'):
    files.append(i)

for f in files:
    with open('path_to_dir_with_files'+str(f), 'r') as a:
       pars.append(re.sub(r'\n(?=\n)','',a.read()))

for k in pars:
   print k

注意:如果files [0]的最后一个字符是\n,而file [1]的第一个字符也是'\n',那么这并不能帮助你,但是...你可以使用strip来解决这个问题,你的打印语句会处理文件之间的单个空格。
import os
import re

files=[]
pars=[]

for i in os.listdir('path_to_dir_with_files'):
    files.append(i)

for f in files:
    with open('path_to_dir_with_files'+str(f), 'r') as a:
       pars.append(re.sub(r'\n(?=\n)','',a.read().strip()))

for k in pars:
   print k

-3

只是想指出一点:正则表达式并不是处理这个问题的最佳方法。在 Python str 中用一个很简单的方式将两个空行替换为一个,无需使用 re:

entire_file = "whatever\nmay\n\nhappen"
entire_file = entire_file.replace("\n\n", "\n")

完成了!比re快得多(我个人认为)也更易于阅读。


如果文件包含超过2个连续的“\n”,例如“whatever\nmay\n\n\nhappen”,则此方法将无法正常工作。 - Yuri Olive
2
没错,但还是可以用循环来实现:while "\n\n" in text: text = text.replace("\n\n", "\n") - vincent-lg
这种“省略”形式很脆弱,需要根据所需运行的长度进行适应。例如,希望在“段落”之间有两个换行符,需要进行三次.replace("\n\n\n", "\n\n")调用。迭代重构意味着每次迭代都要复制整个字符串。正则表达式可以更轻松地组合_实际测量的重复字符运行_,并对运行长度进行明确控制:\n{min,max},并在基本上O(1)时间内执行此操作,而不会过度复制内存。 - amcgregor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接