2012-03-12 13 views
4

我有一个特殊的用例,我还不知道如何覆盖。我想根据field_name/field_length剖析一个字符串。为此,我定义了这样一个正则表达式:用python正则表达式解析字符串,使用命名组和替换

'(?P<%s>.{%d})' % (field_name, field_length) 

这对所有字段都重复。

我也有一个正则表达式来删除空格每个字段的右侧:

self.re_remove_spaces = re.compile(' *$') 

这样我可以得到这样的每个字段:

def dissect(self, str): 
    data = { } 
    m = self.compiled.search(str) 
    for field_name in self.fields: 
     value = m.group_name(field_name) 
     value = re.sub(self.re_remove_spaces, '', value) 
     data[field_name] = value 
    return data 

我执行此处理数以百万计的字符串,所以它必须是有效的。

让我感到困扰的是,我宁愿在一个步骤中使用compiled.sub而不是compiled.search来执行解剖+空间去除,但我不知道如何去做。

具体来说,我的问题是:

如何执行正则表达式替换它命名组在Python正则表达式相结合?

+0

你显示的正则表达式(''(?<%s>。%d)'%...',它会变成类似''(? .12)'')不是有效的Python正则表达式。 – interjay 2012-03-12 10:10:12

+0

对不起,已更正:缺少P和{}。我仍在测试这个,所以可能会出现更多的错误。 – dangonfast 2012-03-12 10:14:58

回答

4

我把它的每个字段位于字符串中彼此相邻,就像在一个表,如:

name  description  license 
python language   opensource 
windows operating system proprietry 

所以假设你事先知道每个字段的长度,你可以更简单地做到这一点,根本不使用正则表达式。 (顺便说一句,str不是一个变量一个好名字,因为它有内置的str型擦出)

def dissect(text): 
    data = {} 
    for name, length in fields: 
     data[name] = text[:length].rstrip() 
     text = text[length:] 
    return data 

然后,如果fields = [('lang', 9), ('desc', 19), ('license', 12)]

>>> self.dissect('python language   opensource') 
{'lang': 'python', 'license': 'opensource', 'desc': 'language'} 

这是你想要做什么,虽然?

+0

是的,这正是我想要的,实际上我的第一个实现是使用字符串切片完成的。不知何故,我坚信自己在这种情况下正则表达式会表现得更好,从而将实现更改为带有命名组的正则表达式。我的过程函数现在运行了几个小时,并且告诉你实际情况,我有切片更快的感觉。大概我将它改回来,或者我可以让这两个实现都做性能测试。 – dangonfast 2012-03-12 12:11:50

+0

我想你会发现切片速度要快得多,但是如果它运行了很长时间,那么你应该确定它的位置,看看瓶颈在哪里,以及如何进一步提高速度。 – aquavitae 2012-03-12 12:41:41

+0

需要很长时间,因为有很多记录要处理。 – dangonfast 2012-03-12 12:51:20

0

为什么即使使用sub当你可以直接匹配你想要的部分?

您可以使用类似:

(?P<name>.{0,N}(?<!)) 

但如果比赛必须准确N长,你可以使用一个前瞻,如:

(?=(?P<name>.{0,N}(?<!))).{N} 

如果这是性能更好的比使用额外的修剪是有问题的。你可以尝试一下,让我们知道。

如果匹配只是空格,而且它之前的字符也是空格,则这些表达式将不起作用。如果你需要的话工作,你可以在组的末尾添加|

(?P<name>.{0,N}(?<!)|) 
+0

是的,字段可以是所有空格,前面的字段也可以是空格。和领域有一个确切的长度。 – dangonfast 2012-03-12 12:15:17

+0

@gonvaled,那么你可以使用第二个表达式和最后一条建议:'(?=(?P 。{0,N}(?<!)|))。{N}' – Qtax 2012-03-12 12:17:04

+0

我无法修改输入数据。添加'|'是不可能的。 – dangonfast 2012-03-30 08:27:36