用python中的re.sub替换特定的命名组

时间:2016-08-02 01:15:47

标签: python regex string-substitution

我创建一个正则表达式来查找/places/:state/:city/whatever

等网址
p = re.compile('^/places/(?P<state>[^/]+)/(?P<city>[^/]+).*$')

这很好用:

import re

p = re.compile('^/places/(?P<state>[^/]+)/(?P<city>[^/]+).*$')
path = '/places/NY/NY/other/stuff'
match = p.match(path)
print match.groupdict()

打印{'city': 'NY', 'state': 'NY'}

如何处理日志文件以将/places/NY/NY/other/stuff替换为字符串"/places/:state/:city/other/stuff"?我想了解#34;城市类型的网址数量是多少?#34;没有关心这些地方(NYNY)具体。

简单的方法可能会失败:

import re

p = re.compile('^/places/(?P<state>[^/]+)/(?P<city>[^/]+).*$')
path = '/places/NY/NY/other/stuff'
match = p.match(path)
if match:
  groupdict = match.groupdict()
  for k, v in sorted(groupdict.items()):
    path = path.replace(v, ':' + k, 1)
print path

将打印/places/:city/:state/other/stuff,这是向后的!

感觉应该有某种方式使用re.sub,但我无法看到它。

1 个答案:

答案 0 :(得分:1)

找出更好的方法来做到这一点。编译的正则表达式上有一个属性groupindex,它在模式字符串中打印组及其顺序

>>> p = re.compile('^/places/(?P<state>[^/]+)/(?P<city>[^/]+).*$')
>>> p.groupindex
{'city': 2, 'state': 1}

可以按正确的顺序轻松迭代:

>>> sorted(p.groupindex.items(), key=lambda x: x[1])
[('state', 1), ('city', 2)]

使用这个,我应该能够保证我以正确的从左到右的顺序替换匹配:

p = re.compile('^/places/(?P<state>[^/]+)/(?P<city>[^/]+).*$')
path = '/places/NY/NY/other/stuff'
match = p.match(path)
if match:
    groupdict = match.groupdict()
    for k, _ in sorted(p.groupindex.items(), key=lambda x: x[1]):
        path = path.replace(groupdict[k], ':' + k, 1)
print path

这会以正确的顺序循环遍历组,这可确保替换也以正确的顺序发生,从而可靠地生成正确的字符串:

/places/:state/:city/other/stuff