python - 用适当的元素替换贪婪的元素

标签 python regex

我有一个这样的列表:

import re
l = ['Part I,   Where I’M Coming From',
 'Part Ii,  Life Principles',
 'Part Iii, Work Principles']

我想要一个结果

l = ['Part I,   Where I’M Coming From',
     'Part II,  Life Principles',
     'Part III, Work Principles']

我尝试过:

In [19]: [re.sub(r'(?<=I)i+', 'I+', s) for s in l]
Out[19]:
['Part I,   Where I’M Coming From',
 'Part II+,  Life Principles',
 'Part II+, Work Principles']

它输出'第二部分+,工作原则'而不是'第三部分,工作原则'

如何完成这样的任务?

最佳答案

实现此目的的一种简单方法是将 re.sub回调函数结合使用。回调处理比简单替换更复杂的逻辑。在您的情况下,您需要匹配大写 I 后面的所有小写 i,找出有多少个 i,然后替换相应地。

>>> re.sub('(?<=I)(i+)', lambda x: 'I' * len(x.group()), 'Part Iii,  Work Principles')
'Part III,  Work Principles'

如果没有匹配,则不会调用回调(即不发生替换)。

如果您有兴趣更深入地了解所发生的情况,这里有与函数相同的回调,以及几个打印语句。

>>> def replace(m):
...     print(*[m, m.group(), len(m.group())], sep='\n')
...     return 'I' * len(m.group())
... 
>>> re.sub('(?<=I)(i+)', replace, 'Part Iii,  Work Principles')
<_sre.SRE_Match object; span=(6, 8), match='ii'>
ii
2
'Part III,  Work Principles'

你会注意到这个打印出来...

<_sre.SRE_Match object; span=(6, 8), match='ii'>
ii
2

...除了执行替换之外。需要注意的重要一点是,它将一个 match 对象传递给回调函数。然后,您可以找出匹配的内容,并相应地决定用什么替换它。

<小时/>

推广到任意罗马数字

如果您的函数必须匹配任何罗马数字,那么您可以 pass a pattern that finds thosere.sub,但是你的回调大大简化了:

>>> p = r'\bM{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})\b'
>>> string = 'Part viiI,  Work Principles'
>>> re.sub(p, lambda x: x.group().upper(), string, flags=re.IGNORECASE)
'Part VIII,  Work Principles'

现在,您所需要做的就是将匹配的字符串大写。

关于python - 用适当的元素替换贪婪的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48218794/

相关文章:

python - 不区分大小写的 argparse 选择不会丢失选择列表中的大小写信息

python - 从外籍人士的解析错误中优雅地恢复

python - Arduino Yun Python 脚本

不使用 db.eval() 的 django 中用于 mongodb 的 Python ORM

javascript - 如何在 Angularjs 中验证 IpV6 地址

python - 如何在Python中使用re替换和小写2个或更多组

javascript - 允许字母数字、-、_ 和空格的正则表达式

python - 无法从 python 中的 div 标签读取文本

java - 如何编写一个正则表达式来满足所有情况并打印指定变量

regex - python3中 `regs`中 `match`对象的 `re`属性的替代