使用python正则表达式解析字符串,使用命名组和替换

时间:2012-03-12 10:04:59

标签: python regex

我有一个特殊的用例,我还不知道如何覆盖。我想基于field_name / field_length剖析字符串。为此,我定义了一个这样的正则表达式:

'(?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正则表达式中将它与命名组结合使用正则表达式替换?

2 个答案:

答案 0 :(得分: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'}

这是你正在尝试做的吗?

答案 1 :(得分:0)

为什么在您可以直接匹配所需的部分时使用sub

您可以使用以下内容:

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

但如果匹配必须完全N长,您可以使用前瞻,例如:

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

如果这比使用额外的修剪更好的表现是值得怀疑的。你可以尝试一下,让我们知道。

如果匹配只是空格,这些表达式将不起作用,而前面的字符也是空格。如果您需要该案例,您可以在小组末尾添加|

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