【发布时间】:2017-01-12 05:04:17
【问题描述】:
我正在尝试处理一个大管道“|”分隔的双引号限定文本文件(>700,000 条记录,每条记录 >3,000 个字符,每条记录 28 个字段)。使用 python 脚本。我遇到了一个问题,因为 csv 解析器由于未转义的双引号字符和嵌入在文件中字段的文本中的管道而错误地解析了字段。由于文件中不存在制表符,我想通过用制表符 (\t) 替换双引号管道双引号分隔符/限定符字符序列 ("|") 将其转换为制表符分隔文件。如果填充了每个字段但有些字段没有填充,这将相对简单。未填充的字段由空字符串表示,因此我可以按顺序使用 1 到 7 个以双引号开头的管道分隔符。
一个简单的例子是:
"abc"|"2016-07-30"|"text narrative field"|"2016-08-01"|"123"|"456"|"789"|"EOR"
一个比较有代表性的例子是:
"abc"|"2017-01-01"|"height: 5' 7" (~180 cm) | weight: 80kg | in good health"|"2016-01-10"||||"EOR"
我一直在尝试编写一个正则表达式,它将每个管道字符/双引号组合或管道字符序列立即替换为带有 TAB 字符的双引号 1 对 1。我发现了许多用单个字符替换重复字符串的正则表达式示例,但没有一个用等长字符串替换一系列重复字符的替代字符。
我尝试了以下正则表达式:"\|{1,}",它适用于单个管道字符,但会用单个 TAB 依次替换多个管道。我还需要处理以下相关方面:
- 删除行首/双引号 (^")
- 删除双引号/行尾 ("$)
- 并将双引号/竖线(1 个或多个)/行尾(例如“\|$)替换为与竖线字符相同数量的 TAB 字符
应用正则表达式后的输出记录如下所示,使用 \t 表示 TAB 字符:
abc\t2016-07-30\ttext narrative field\t2016-08-01\t123\t456\t789\tEOR
abc\t2017-01-01\theight: 5' 7" (~180 cm) | weight: 80kg | in good health\t2016-01-10\t\t\t\tEOR
我愿意在 python 或 linux 中使用 sed 或 awk 解决这个问题
【问题讨论】:
-
csv 解析器不正确地解析字段 - “祈祷,巴贝奇先生,如果你把错误的数字输入机器,正确的答案会出来吗?”。如果您的文件没有有效的逗号分隔值,那么将错误的输出归咎于 csv 解析器有点苛刻:P
-
这取决于解析器。例如,Informatica 可以正确解析上面提供的更复杂的记录。但是,至少在我看来,csv 解析器没有。我预计它会将其解析为:
field 1: abcfield 2: 2017-01-01field 3: height: 5' 7" (~180 cm) | weight: 80kg | in good healthfield 4: 2016-01-10……但是,它会将其解析为:field 1: abcfield 2: 2017-01-01field 3: height: 5' 7" (~180 cm)field 4: weight: 80kgfield 5: in good health@9876543即使在 | 之前还有其他字符,也会在 " 之后中断