【问题标题】:Pattern replacement in lines read from csv using regex in python 3+在 python 3+ 中使用正则表达式从 csv 读取的行中的模式替换
【发布时间】:2020-03-16 01:36:11
【问题描述】:

我必须处理由专有软件创建的格式错误的 csv 文本文件,该软件会更改某些格式(引号、列分隔符、单个小数位浮动到四个小数位和换行符)。我的目标输出是制表符分隔的,unix 换行符和浮点数。

以下是原始文件中的一些示例行:

1234\t5678\t-3461\t56\t10\n
4435.5\t-1261\t56\t10\n
89432\t678112\t-2461\t56\t10\n

这是专有软件的输出(不一定是 4 个十进制浮点数的固定宽度,开发人员可能会在未来的版本中更改此设置):

"1234.0000 5678.0000 -3461.0000 56.0000 10.0000"\r
"4435.5000 -1261.0000 56.0000 10.0000"\r
"89432.0000 678112.0000 -2461.0000 56.0000 10.0000"\r

我在函数中的模式非常冗长,正则表达式可能会写得更简洁,但由于我对正则表达式还不是很熟悉,所以我倾向于保持模式简单易懂。这是我用来重组 csv 文件的每一行的函数:

import re

def Filter(inputLine):
    line = inputLine.strip().lstrip("'").rstrip("'").lstrip('"').rstrip('"') #get rid of internal quotation marks and newline character
    line = re.sub(r'\s','\t', line) #replace whitespaces by tab
    line = re.sub(r'\.0{1,9}','', line) #replace all .0* by single whitespace -  not really working, .5000 for example - think!
    line = f'{line}\n'
    return(line)

#code for parsing each oline of input and so on

到目前为止一切顺利,但正如预期的那样,这不会将第 2 行中的 4435.5000 更改为 4435.5:

1234\t5678\t-3461\t56\t10\n
4435.5000\t-1261\t56\t10\n
89432\t678112\t-2461\t56\t10\n

我想在这个任务中使用正则表达式,即使对于大 (>1GB) 文本文件也有效(我不知道是否有更优雅的解决方案来处理这个操作)

  1. 保持 0.5 但删除所有 0.000 的模式是什么?我正在考虑以下内容,但我被替换部分卡住了:
    line = re.sub(r'\.[1-9]0{1,9}',r'\.[1-9]', line) 

这显然行不通。

  1. 有什么方法可以压缩正则表达式模式?这更出于兴趣,正如我上面提到的,我目前更喜欢单独调用来帮助我理解正则表达式的语法。

欢迎提出任何建议!

干杯 萨沙

【问题讨论】:

  • line = re.sub(r'(\.(\d*?))0+', lambda x: x.group(1) if x.group(2) else '', line) (demo)
  • @WiktorStribiżew 哇!这是一个超级高效的 p​​ython 和正则表达式的非常酷的组合。非常感谢,这解决了我的问题。

标签: regex python-3.x csv


【解决方案1】:

你可以使用

line = re.sub(r'(\.(\d*?))0+', lambda x: x.group(1) if x.group(2) else '', line)

请参阅Python demo

它是这样工作的:

  • (\.(\d*?)) - 将一个点和 0 个或更多数字匹配并捕获到第 1 组,但尽可能少,同时将这些数字捕获到第 2 组,
  • 0+ - 匹配一个或多个 0 字符
  • lambda x: x.group(1) if x.group(2) else '' 如果 Group 2 不为空,则将匹配替换为 Group 1 的内容,否则,整个匹配被删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-06
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 2017-08-18
    • 1970-01-01
    • 2017-04-30
    • 2020-09-17
    相关资源
    最近更新 更多