使用python在列表中提取正则表达式元素

时间:2018-03-14 09:02:15

标签: python regex list element

我有一个包含一组文件历史记录的列表。我需要将列表中的每个元素分成几列并将其保存到CSV文件中。

我需要的列是commit_id, filename, committer, date, time, line_number, code。 假设,这是我的清单:

my_list = [
     'f5213095324 master/ActiveMasterManager.java              (Michael Stack      2010-08-31 23:51:44 +0000   1) /**',
     'f5213095324 master/ActiveMasterManager.java              (Michael Stack      2010-08-31 23:51:44 +0000   2)  *',
     'f5213095324 master/ActiveMasterManager.java              (Michael Stack      2010-08-31 23:51:44 +0000   3)  * Licensed to the Apache Software Foundation (ASF) under one',
     'f5213095324 master/ActiveMasterManager.java              (Michael Stack      2010-08-31 23:51:44 +0000   4)  * or more contributor license agreements.',
     ...
     'b5cf8748198 master/ActiveMasterManager.java              (Michael Stack      2012-09-27 05:40:09 +0000 160)           if (ZKUtil.checkExists(this.watcher, backupZNode) != -1) {'
     ]

所需的csv输出:

commit_id   | filename                         | committer     | date       | time     | line_number | code 
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
f5213095324 | master/ActiveMasterManager.java  | Michael Stack | 2010-08-31 | 23:51:44 | 1           | /**
f5213095324 | master/ActiveMasterManager.java  | Michael Stack | 2010-08-31 | 23:51:44 | 2           | *
f5213095324 | master/ActiveMasterManager.java  | Michael Stack | 2010-08-31 | 23:51:44 | 3           | * Licensed to the Apache Software Foundation (ASF) under one
f5213095324 | master/ActiveMasterManager.java  | Michael Stack | 2010-08-31 | 23:51:44 | 4           | * or more contributor license agreements.
........
b5cf8748198 | master/ActiveMasterManager.java  | Michael Stack | 2012-09-27 | 05:40:09 | 160         | if (ZKUtil.checkExists(this.watcher, backupZNode) != -1) {

我尝试使用此代码:

pattern = re.compile(r'(?P<commit_id>\w+)\s+(?P<filename>[^\s]+)\s+\((?P<committer>.+)\s+(?P<date>\d{4}-\d\d-\d\d)\s+(?P<time>\d\d:\d\d:\d\d).+(?P<line_number>\b\d+\b)\)\s+(?P<code>[^"]*)')

with open('somefile.csv', 'w+', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(['commit_id', 'filename', 'committer', 'date', 'time', 'line_number', 'code'])
    for line in my_list:
        writer.writerow([field.strip() for field in pattern.match(line).groups()])

通常,代码有效。 但是对于line number = 160,它在-1列中写了line_number,而在{列中只写code

正则表达式中是否缺少某些内容?

3 个答案:

答案 0 :(得分:1)

我修复了正则表达式。 这应该有效:

pattern = re.compile(r'(?P<commit_id>\w+)\s+(?P<filename>[^\s]+)\s+\((?P<committer>.+)\s+(?P<date>\d{4}-\d\d-\d\d)\s+(?P<time>\d\d:\d\d:\d\d).+?(?P<line_number>\b\d+\b)\)\s+(?P<code>[^"]*)')

我添加了一个问号以使用Lazy匹配 &#34;。+&#34; =&GT; &#34;。+&#34?;

https://regex101.com/r/GQGLvy/1

答案 1 :(得分:1)

您的模式的主要问题是使用.+。如果用.*?替换它,您不仅可以解决行号问题,还可以在提交者名称后删除空格:

pattern = re.compile(r'(?P<commit_id>\w+)\s+(?P<filename>[^\s]+)\s+\((?P<committer>.*?)\s+(?P<date>\d{4}-\d\d-\d\d)\s+(?P<time>\d\d:\d\d:\d\d).*?(?P<line_number>\b\d+\b)\)\s+(?P<code>[^"]*)')

https://regex101.com/r/f7zjpA/2

修改

你没有提到你想保留缩进,而你的代码看起来并不像你真正想要的那样。删除代码之前的空格/缩进不仅因为正则表达式模式。有两件事:

  • 在正则表达式模式中,您在\s+组之前使用了code,这排除了所有空格/缩进。如果您想保留它们,请将\s+替换为\s,而pattern = re.compile(r'(?P<commit_id>\w+)\s+(?P<filename>[^\s]+)\s+\((?P<committer>.*?)\s+(?P<date>\d{4}-\d\d-\d\d)\s+(?P<time>\d\d:\d\d:\d\d).*?(?P<line_number>\b\d+\b)\)\s(?P<code>[^"]*)') 只会捕获第一个而不是所有这些:

    field.strip()
  • 在你使用writer.writerow([field.strip() for field in pattern.match(line).groups()]) 的for循环中
  • 删除了字符串开头和结尾的所有空格。修改模式并进行交换:

    writer.writerow(pattern.match(line).groups())
    

    使用:

    <?php
    // src/Controller/LuckyController.php
    
    namespace App\Controller;
    use Symfony\Component\HttpFoundation\Response;
    class LuckyController
    {
        public function number()
        {
            $number = mt_rand(0, 100);
    
            return new Response(
                '<html><body>Lucky number: '.$number.'</body></html>'
            );
        }
    }
    

    将导致缩进它们所属的位置。

答案 2 :(得分:0)

不完全是你在找,但这很有用。

import re

for row in my_list:
    print([x.strip() for x in re.split(r"(?![)])\s+(?![(])", row)])

out:

['f5213095324', 'master/ActiveMasterManager.java', '(Michael', 'Stack', '2010-08-31', '23:51:44', '+0000', '1)', '/**']
['f5213095324', 'master/ActiveMasterManager.java', '(Michael', 'Stack', '2010-08-31', '23:51:44', '+0000', '2)', '*']
...