Python 如何读取某些内容有换行符的文本文件?
我有以下表格的文本文件:Python 如何读取某些内容有换行符的文本文件?,python,Python,我有以下表格的文本文件: 2016年1月6日,晚上10:40-abcde 2016年1月7日,下午12:04-abcde 2016年1月7日,下午12:05-abcde 2016年1月7日,下午12:05-abcde 2016年1月7日下午6:14-abcde fghe 2016年1月7日下午6:20-abcde 2016年1月7日,下午7:58-abcde fghe ijkl 2016年1月7日,下午7:58-abcde 您可以看到,每一行都由换行符分隔,但某些行内容中有换行符。因此,简单地
2016年1月6日,晚上10:40-abcde
2016年1月7日,下午12:04-abcde
2016年1月7日,下午12:05-abcde
2016年1月7日,下午12:05-abcde
2016年1月7日下午6:14-abcde
fghe
2016年1月7日下午6:20-abcde
2016年1月7日,下午7:58-abcde
fghe
ijkl
2016年1月7日,下午7:58-abcde
您可以看到,每一行都由换行符分隔,但某些行内容中有换行符。因此,简单地按行分隔并不能正确地解析每一行
例如,对于第5个条目,我希望输出为
2016年1月7日下午6:14-abcde fghe
这是我目前的代码:
with open('file.txt', 'r') as text_file:
data = []
for line in text_file:
row = line.strip()
data.append(row)
您可以使用正则表达式(使用模块)检查如下日期:
import re
with open('file.txt', 'r') as text_file:
data = []
for line in text_file:
row = line.strip()
if re.match(r'\d{2}/\d{2}/\d{4}.*'):
data.append(row) # date: new record
else:
data[-1] += '\n' + row # no date: append to last record
# '\d{2}': two digits
# '.*': any character, zero or more times
考虑到“
”,“
只能作为分隔符出现,我们可以检查该行是否有逗号,如果没有,则将其连接到最后一行:
data = []
with open('file.txt', 'r') as text_file:
for line in text_file:
row = line.strip()
if ',' not in row:
data[-1] += '\n' + row
else:
data.append(row)
长度的简单测试:
#!python3
#coding=utf-8
data = """06/01/2016, 10:40 pm - abcde
07/01/2016, 12:04 pm - abcde
07/01/2016, 12:05 pm - abcde
07/01/2016, 12:05 pm - abcde
07/01/2016, 6:14 pm - abcde
fghe
07/01/2016, 6:20 pm - abcde
07/01/2016, 7:58 pm - abcde
fghe
ijkl
07/01/2016, 7:58 pm - abcde"""
lines = data.split("\n")
out = []
for l in lines:
c = l.strip()
if c:
if len(c) < 10:
out[-1] += c
else:
out.append(c)
#skip empty
for o in out:
print(o)
数据中不包含换行符
但是这个单行正则表达式应该做到这一点(在linebreak上拆分,后跟数字),至少对于示例数据(当数据包含linebreak,后跟数字时会中断): 输出:
['06/01/2016, 10:40 pm - abcde', '07/01/2016, 12:04 pm - abcde', '07/01/2016, 12:05 pm - abcde', '07/01/2016, 12:05 pm - abcde', '07/01/2016, 6:14 pm - abcde\n\
nfghe', '07/01/2016, 6:20 pm - abcde', '07/01/2016, 7:58 pm - abcde\n\nfghe\n\nijkl', '07/01/2016, 7:58 pm - abcde']
06/01/2016, 10:40 pm - abcde
07/01/2016, 12:04 pm - abcde
07/01/2016, 12:05 pm - abcde
07/01/2016, 12:05 pm - abcde
07/01/2016, 6:14 pm - abcde
fghe
07/01/2016, 6:20 pm - abcde
07/01/2016, 7:58 pm - abcde
fghe
ijkl
07/01/2016, 7:58 pm - abcde
(使用前瞻性修复)给定示例输入,您可以使用带有前瞻性的:
pat=re.compile(r'^(\d\d\/\d\d\/\d\d\d\d.*?)(?=^^\d\d\/\d\d\/\d\d\d\d|\Z)', re.S | re.M)
with open (fn) as f:
pprint([m.group(1) for m in pat.finditer(f.read())])
印刷品:
['06/01/2016, 10:40 pm - abcde\n',
'07/01/2016, 12:04 pm - abcde\n',
'07/01/2016, 12:05 pm - abcde\n',
'07/01/2016, 12:05 pm - abcde\n',
'07/01/2016, 6:14 pm - abcde\n\nfghe\n',
'07/01/2016, 6:20 pm - abcde\n',
'07/01/2016, 7:58 pm - abcde\n\nfghe\n\nijkl\n',
'07/01/2016, 7:58 pm - abcde\n']
在Dropbox示例中,打印:
['11/11/2015, 3:16 pm - IK: 12\n',
'13/11/2015, 12:10 pm - IK: Hi.\n\nBut this is not about me.\n\nA donation, however small, will go a long way.\n\nThank you.\n',
'13/11/2015, 12:11 pm - IK: Boo\n',
'15/11/2015, 8:36 pm - IR: Root\n',
'15/11/2015, 8:36 pm - IR: LaTeX?\n',
'15/11/2015, 8:43 pm - IK: Ws\n']
如果要删除捕获内容中的\n
,只需将m.group(1).strip()添加到上面的列表中。替换('\n','')
正则表达式的解释:
^(\d\d\/\d\d\/\d\d\d\d.*?)(?=^^\d\d\/\d\d\/\d\d\d\d|\Z)
^ start of line
^ ^ ^ ^ ^ pattern for a date
^ capture the rest...
^ until (look ahead)
^ ^ ^ another date
^ or
^ end of string
可能包含换行符的数据本身是否包含在双引号中?您是否可以演示
数据的外观?从你的描述中不清楚。我看到了收入,但不清楚结果应该如何。我希望数据的每个元素都以日期开头。@juanpa.arrivillaga是的is@Imran那么你可能有某种类型的CSV。如果您知道分隔符是什么,您可以使用csv
模块轻松地完成此操作。您可以发布数据的前几行吗?如果数据包含linebreak+数字,则会失败,因此需要扩展正则表达式。另一方面,如果数据包含一个新行,该新行看起来像是数据头,那么这种方法[没有清理数据,没有分隔符]很容易被破坏……如果其中一个日期是12/21/2016
?如果你使用re.split(r'\n\d',txt)
你的日期变成了2/21/2016
…哎呀,没有注意到它消耗了这个数字。你可以通过前瞻来解决这个问题——就像我发布的这个解决方案:re.split(r'\n(?=^\d'),txt)
还不知道\Z
,谢谢。[好的,你又删除了它..]到目前为止,没有任何东西阻止逗号出现在数据中(实际上,在问题注释中链接的数据文件中,有几个逗号)。可靠的分离是不可能的。当我发表文章时,只有问题中的例子,我的代码将是“可能工作的最简单的东西”。但是,如果在注释中链接了数据,您是对的,它将无法工作……与目前为止的任何其他方法一样:如果数据包含分隔符序列(此格式的日期),则会中断。这非常有效,谢谢!你能解释一下re.compile
中的代码是做什么的吗?
['11/11/2015, 3:16 pm - IK: 12\n',
'13/11/2015, 12:10 pm - IK: Hi.\n\nBut this is not about me.\n\nA donation, however small, will go a long way.\n\nThank you.\n',
'13/11/2015, 12:11 pm - IK: Boo\n',
'15/11/2015, 8:36 pm - IR: Root\n',
'15/11/2015, 8:36 pm - IR: LaTeX?\n',
'15/11/2015, 8:43 pm - IK: Ws\n']
^(\d\d\/\d\d\/\d\d\d\d.*?)(?=^^\d\d\/\d\d\/\d\d\d\d|\Z)
^ start of line
^ ^ ^ ^ ^ pattern for a date
^ capture the rest...
^ until (look ahead)
^ ^ ^ another date
^ or
^ end of string