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