Python多个正则表达式清理文件

时间:2017-09-05 17:22:46

标签: python regex removing-whitespace

前言

我有一段时间没有使用python,因此我遇到了数据清理方面的问题。 在notepad ++中它变得非常慢,所以我在python中寻找更有效的选项。

我需要什么

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

我正在寻找的步骤:

  1. 使用-----
  2. 删除第一行
  3. 使用-----
  4. 删除第三行
  5. 从每行中删除第一个和最后一个字符|
  6. 删除需要的空格 - 我需要保留文本之间
  7. 原始文件

    ---------------------------------------------------------------------------
    |  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是我尝试使用的代码,但我需要有关正则表达式组合的帮助。在Notepad ++中,我可以使用\h+(\w+)\h+并替换\1,但在这里它不起作用。请帮我构建一个正确的正则表达式。

3 个答案:

答案 0 :(得分:3)

两种方法:

使用内置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')

答案 1 :(得分:0)

WRT参考代码片段,您可以使用以下模式:

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

答案 2 :(得分:0)

前言

假设您的所有文件格式相同,您只需使用正则表达式替换。

答案

您可以在regex101 here

上查看此内容

解释

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

  1. 抓住所有制表符或空格字符
  2. 抓住所有-个字符,其中两个此类字符互相跟随(以及任何后续空格字符)
  3. 抓住以|字符
  4. 开头的所有行
  5. 抓住所有以|字符结尾的行
  6. 请注意,您必须确保全局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. 抓住|
    6. 之前的任意数量的制表符或空格字符
    7. 抓住所有-个字符,其中两个此类字符互相跟随(以及任何后续空格字符)
    8. 请注意,您必须确保全局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