【问题标题】:Python multiple regexes cleaning the filePython多个正则表达式清理文件
【发布时间】:2017-09-06 22:44:22
【问题描述】:

前言

我已经有一段时间没有使用 python 了,所以我在数据清理方面遇到了问题。 在记事本++中运行速度非常慢,所以我正在寻找更有效的python选项。

我需要什么

我需要清理一个目录中的 100 多个文件,所有这些文件都是从 SAP 中手动提取的。

我正在寻找的步骤:

  1. 删除第一行-----
  2. 删除第三行-----
  3. 从每行删除第一个和最后一个字符|
  4. 在需要的地方删除空格 - 我需要在文本之间保留它们

原始文件

---------------------------------------------------------------------------
|  MANDT|BUKRS|NETWR     |UMSKS|UMSKZ|AUGDT     |AUGBL|ZUONR              |
---------------------------------------------------------------------------
|  100  |1000 |23.321-   |     |     |          |     |TEXT I WANT TO KEEP|
|  100  |1000 |0.12      |     |     |          |     |TEXT I WANT TO KEEP|
|  100  |1500 |90        |     |     |          |     |TEXT I WANT TO KEEP|
---------------------------------------------------------------------------

预期结果

MANDT|BUKRS|NETWR|UMSKS|UMSKZ|AUGDT|AUGBL|ZUONR
100|1000|23.321-|||||TEXT I WANT TO KEEP
100|1000|0.12|||||TEXT I WANT TO KEEP
100|1500|90|||||TEXT I WANT TO KEEP

代码here 是我正在尝试使用的代码,但我需要正则表达式组合方面的帮助。在记事本++ 中,我可以使用\h+(\w+)\h+ 并替换\1,但在这里它不起作用。请帮我建立一个合适的正则表达式。

【问题讨论】:

  • 忽略没有| 的行,在| 上拆分,修剪,使用| 连接值。这个算法不需要正则表达式。
  • 事情就像我提到的那样,我已经有一段时间没有使用 python了——我想大约有 1 年了。可以分享一些代码片段吗?

标签: python regex removing-whitespace


【解决方案1】:

两种方法:

-- 使用内置的str 对象函数:

with open('yourfile.txt', 'r') as f:
    lines = f.read().splitlines()     # getting list of lines
    for l in lines:
        if not l.startswith('---'):   # skip dashed lines
            print('|'.join(map(str.strip, l.strip('|').split('|'))))

--使用re.sub()函数:

with open('yourfile.txt', 'r') as f:
    lines = f.read().splitlines()
    for l in lines:
        if not l.startswith('---'):
            print(re.sub(r'\|\s*|\s*\|', '|', l).strip('|'))
            # an auxiliary pattern for complex cases:
            # re.sub(r'\|\s*(\S*)\s*(?=\|)', '|\\1', l).strip('|')

输出:

MANDT|BUKRS|NETWR|UMSKS|UMSKZ|AUGDT|AUGBL|ZUONR
100|1000|23.321-|||||TEXT I WANT TO KEEP
100|1000|0.12|||||TEXT I WANT TO KEEP
100|1500|90|||||TEXT I WANT TO KEEP

读/写模式:

要使用新内容覆盖当前文件,请使用以下方法:

with open('yourfile.txt', 'r+') as f:   # 'r+' - read/write mode
    lines = f.read().splitlines()
    f.seek(0)      # reset file pointer
    f.truncate()   # truncating file contents
    for l in lines:
        if not l.startswith('---'):
            # or f.write('|'.join(map(str.strip, l.strip('|').split('|'))) + '\n')
            f.write(re.sub(r'\|\s*|\s*\|', '|', l).strip('|') + '\n')

【讨论】:

  • 聪明!开箱即用的想法与走正则表达式路线相比很好
  • 如何覆盖我正在使用的文件?我不想打印它。我正在尝试使用 l='|'.join(map(str.strip, l.strip('|').split('|'))) 但它不起作用。
  • @user2433705,看看我最后的方法
  • @RomanPerekhrest,我还需要更新一件事 - 如何修改正则表达式以删除在数字之前弹出的空格 - 我没有将它包含在原始示例中。所以就我而言,我有| 100 |1000 | 23.321- | | | | |TEXT I WANT TO KEEP|
  • @user2433705,在评论# an auxiliary pattern for complex cases:下查看我的更新
【解决方案2】:

前言

假设您所有的文件都采用相同的格式,您可以简单地使用正则表达式替换。

回答

您可以在 regex101 here 上查看此使用情况

说明

这个正则表达式[\t ]|-{2,}\s*|^\||\|$ 将:

  1. 捕获所有制表符或空格字符
  2. 捕获所有- 字符,其中两个这样的字符相互跟随(以及任何后面的空白字符)
  3. 捕获所有以| 字符开头的行
  4. 捕获所有以| 字符结尾的行

请注意,您必须确保全局 g 和多行 m 修饰符处于活动状态。


代码

您的最终代码应如下所示:

import re

regex = r"[\t ]|-{2,}\s*|^\||\|$"

subst = ""

result = re.sub(regex, subst, test_str, 0, re.MULTILINE)

if result:
    print (result)

其中test_str 包含文件的内容(如下所示)

---------------------------------------------------------------------------
|  MANDT|BUKRS|NETWR     |UMSKS|UMSKZ|AUGDT     |AUGBL|ZUONR              |
---------------------------------------------------------------------------
|  100  |1000 |23.321-   |     |     |          |     |TEXT I WANT TO KEEP|
|  100  |1000 |0.12      |     |     |          |     |TEXT I WANT TO KEEP|
|  100  |1500 |90        |     |     |          |     |TEXT I WANT TO KEEP|
---------------------------------------------------------------------------

输出

MANDT|BUKRS|NETWR|UMSKS|UMSKZ|AUGDT|AUGBL|ZUONR
100|1000|23.321-|||||TEXTIWANTTOKEEP
100|1000|0.12|||||TEXTIWANTTOKEEP
100|1500|90|||||TEXTIWANTTOKEEP

编辑

回答

您可以在 regex101 here 上查看此使用情况

说明

(?:^\|[\t ]*)|(?:[\t ]*\|$)|(?:(?<=\|)[\t ]*)|(?:[\t ]*(?=\|))|(?:-{2,}\s*)

上面的正则表达式将:

  1. 捕捉|(仅在行首)后跟任意数量的制表符或空格字符
  2. 捕捉任意数量的制表符或空格字符,后跟|(仅在行尾)
  3. 捕捉| 后面的任意数量的制表符或空格字符
  4. 捕捉| 前面的任意数量的制表符或空格字符
  5. 捕获所有- 字符,其中两个此类字符相互跟随(以及任何后续空白字符)

请注意,您必须确保全局 g 和多行 m 修饰符处于活动状态。


代码

您的最终代码应如下所示:

import re

regex = r"(?:^\|[\t ]*)|(?:[\t ]*\|$)|(?:(?<=\|)[\t ]*)|(?:[\t ]*(?=\|))|(?:-{2,}\s*)"

subst = ""

result = re.sub(regex, subst, test_str, 0, re.MULTILINE)

if result:
    print (result)

其中test_str 包含文件的内容(如下所示)

---------------------------------------------------------------------------
|  MANDT|BUKRS|NETWR     |UMSKS|UMSKZ|AUGDT     |AUGBL|ZUONR              |
---------------------------------------------------------------------------
|  100  |1000 |23.321-   |     |     |          |     |TEXT I WANT TO KEEP|
|  100  |1000 |0.12      |     |     |          |     |TEXT I WANT TO KEEP|
|  100  |1500 |90        |     |     |          |     |TEXT I WANT TO KEEP|
---------------------------------------------------------------------------

输出

MANDT|BUKRS|NETWR|UMSKS|UMSKZ|AUGDT|AUGBL|ZUONR
100|1000|23.321-|||||TEXT I WANT TO KEEP
100|1000|0.12|||||TEXT I WANT TO KEEP
100|1500|90|||||TEXT I WANT TO KEEP

【讨论】:

  • 非常感谢,但是如何调整它以不删除文本之间的空格?我在那里还有一些文本属性,我需要保留空格。
【解决方案3】:

WRT 参考中的代码 sn-p,您可以使用以下模式:

REGEXES = [(re.compile(r'^[-\n]+',re.M), ''),
       (re.compile(r'([\s]+)?\|([\s]+)?'), '|')]

【讨论】:

  • 它在 'gm 部分出现语法错误 - 这是什么意思?
  • 我想使用^ 来指示需要设置多行标志的行的开头。 Example。我已经用正确的语法更新了我的答案。
猜你喜欢
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-27
  • 2010-12-31
  • 1970-01-01
相关资源
最近更新 更多