【问题标题】:Read csv into dataframe by ignoring "LF" and "CR LF" within field enclosure quotes (" ")通过忽略字段附件引号 (" ") 中的 "LF" 和 "CR LF" 将 csv 读入数据帧
【发布时间】:2021-07-07 20:39:34
【问题描述】:

我有一个数据文件,其中的字段用双引号和字段分隔符括起来,如下所示:

field enclosure = "<field_value>"
sep = ||@@##

因此,字段值的引号中的文本具有 'LF' 和 'CR LF' 行分隔符,这导致下一行打印在新行上 - 这可能被误解为新记录,当现实,它是一个记录的一部分,有没有被打破的线路转移到一个新的线路。

示例:

3||@@##14||@@##"2016-01-13 19:59:27"||@@##"2016-01-15 23:09:19"||@@##1162||@@##822||@@##1237||@@##\N||@@##"VHiujdfYshv"||@@##"---<LF>
...LF
"||@@##\N||@@##"2016-01-15 23:09:18"||@@##0||@@##1||@@##0||@@##0||@@##3||@@##1788||@@##\N||@@##205||@@##\N||@@##0||@@##\N||@@##\N||@@##\N||@@##\N||@@##\N||@@##\N||@@##1||@@##\N||@@##"251 Bgegf BHVcvytd Street<CR LF>
JHbsdbfh, RF 35214<CR LF>
<CR LF>
xyz@gmail.dhg.com<CR LF>
<CR LF>
@@##1788<LF>
4||@@##14||@@##"2016-01-25 22:08:53"||@@##"2016-02-15 20:32:08"||@@##1097||@@##933||@@##1262||@@##\N||@@##"VHiujdfYshv"||@@##"--- <LF>
...<LF>

请注意,LFCR LF 实际上显示时没有尖括号,这可能是给定的,但我提到它是为了绝对清楚。下面是在记事本++文件上的外观片段。另外请注意,我的数据由 '||@@##' 作为字段分隔符组成,na_values 使用 '\N'。

以下是我目前阅读此文件的方式。我尝试使用 pd.read_csv 中的 'quotechar' 和 'quoting' 参数,但它使用 C 解析器,其中分隔符使用 Python 解析器,因此 python 解析器被覆盖。如何读取此文件

df =  pd.read_csv(z.open(filename), 
                              encoding = 'utf8',
                              header=None,
                              sep='\|\|@@##',
                              na_values='\\N',
                             engine = 'python')

【问题讨论】:

  • 你想用正则表达式实现什么?删除换行符?
  • 是的,那些打破我记录的换行符,无论是 CRLF 还是 LF,都应该只显示在一行中,而不是*单独的行中。
  • 看起来你只有在记录中才有 CRLF,如果你删除它们,记录将在一行上。然后,尝试with open(filepath, 'rb') as file: with open(savefilepath, 'w', encoding='utf-8') as fw: fw.write( file.read().replace(b'\r\n', b'').decode('utf-8') )。然后您可以将savefilepath 文件读入带有pandas 的数据框。
  • 您不必保存文件。但是,由于您的匹配跨越多行,您必须将整个文件读入内存。基本上,您需要使用with open(filepath, 'r') as file: content = re.sub(r'"[^"]*"', lambda x: x.group().replace("\n", ""), file.read())。如果文件乱七八糟,你可能需要with open(filepath, 'r', newline="\n") as file: content = re.sub(r'"[^"]*"', lambda x: re.sub(r'[\u000A-\u000D\u0020\u0085\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]', '', x.group()), file.read())
  • 好的,here is the demo

标签: python regex csv


【解决方案1】:

你可以使用

rx_lbr = r'[\r\n\x0B\x0C\u0085\u2028\u2029]+'
with open(filepath, 'r', newline="\n", encoding="utf-8") as fr:
  with open(savefilepath, 'w', newline="\n", encoding="utf-8") as fw:
    fw.write( re.sub(r'"[^"]*"', lambda x: re.sub(rx_lbr, '', x.group()), fr.read()) )

带有re.sub"[^"]*" 正则表达式匹配单引号之间的所有非重叠子字符串,而lambda x: re.sub(rx_lbr, '', x.group()) 替换仅从匹配项中删除所有垂直空白Unicode 字符。因此,所有其他换行符保持不变。

Python demo

import re
content = r"""3||@@##14||@@##"2016-01-13 19:59:27"||@@##"2016-01-15 23:09:19"||@@##1162||@@##822||@@##1237||@@##\N||@@##"VHiujdfYshv"||@@##"---
...
"||@@##\N||@@##"2016-01-15 23:09:18"||@@##0||@@##1||@@##0||@@##0||@@##3||@@##1788||@@##\N||@@##205||@@##\N||@@##0||@@##\N||@@##\N||@@##\N||@@##\N||@@##\N||@@##\N||@@##1||@@##\N||@@##"251 Bgegf BHVcvytd Street
JHbsdbfh, RF 35214
 
xyz@gmail.dhg.com
 
@@##1788
4||@@##14||@@##"2016-01-25 22:08:53"||@@##"2016-02-15 20:32:08"||@@##1097||@@##933||@@##1262||@@##\N||@@##"VHiujdfYshv"||@@##"---
"""
print( re.sub(r'"[^"]*"', lambda x: re.sub(r'[\r\n\x0B\x0C\u0085\u2028\u2029]+', '', x.group()), content) )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多