如何替换所有出现的正则表达式,就像重复应用替换一样

时间:2016-03-11 19:11:19

标签: python regex

例如,我的文字有很多产品尺寸,例如“2x4”,我想将其转换为“2 x 4”。

pattern = r"([0-9])\s*[xX\*]\s*([0-9])"

re.sub(pattern, r"\1 xby \2", "2x4")
'2 xby 4' # good

re.sub(pattern, r"\1 xby \2", "2x4x12")
'2 xby 4x12' # not good. need this to be '2 xby 4 xby 12'

描述我想要做的事情的一种方法是重复替换,直到不能再进行替换。例如,我可以简单地对上面的替换进行两次以获得我想要的东西

x = re.sub(pattern, r"\1 xby \2", "2x4x12")
x = re.sub(pattern, r"\1 xby \2", x)
'2 xby 4 xby 12'

但我认为有更好的方法

3 个答案:

答案 0 :(得分:5)

您可以使用此前瞻性正则表达式进行搜索:

r'([0-9]+)\s*[xX*]\s*(?=[0-9]+)'

(?=[0-9]+)是一个积极的先行者,只是通过向前看来断言存在第二个数字,但是不会通过匹配数字来移动内部正则表达式指针。

并将其用于替换:

r'\1 xby '

RegEx Demo

<强>代码:

>>> pattern = r'([0-9]+)\s*[xX*]\s*(?=[0-9]+)'

>>> re.sub(pattern, r'\1 xby ', "2x4")
'2 xby 4'

>>> re.sub(pattern, r'\1 xby ', "2x4x12")
'2 xby 4 xby 12'

答案 1 :(得分:1)

我认为你可以通过一次通过来解决这个问题。你真正想要做的是用xby替换x - 所以你可以扫描整个字符串一次,如果你不消耗数字的右边。

为此,我建议使用前瞻性断言。基本上,确认您要替换的东西后跟数字,但不要吃过程中的数字。这种表示法是(?= ...) - 见re docpage

对我来说,我有以下内容 - 请注意,编译正则表达式是可选的,\ d通常优先于[0-9]:

pattern = re.compile(r"(\d+)\s*[xX\*]\s*(?=\d)")
pattern.sub(r"\1 xby ", "2x4x12")

'2 xby 4 xby 12'

在一次传递中,它将处理整个字符串。

答案 2 :(得分:0)

由于您正在尝试针对已由正则表达式转换的文本重新运行匹配,因此实际上并没有更好的方法。

这有点像解开数学问题,如果你想这样做:(2 + 3)+ 4,你需要更换&#34;(2 + 3)&#34 ;能够取代&#34; 5 + 4&#34;因为字符串&#34; 5&#34;原文中没有任何内容。

您可能想要做的是测试您的字符串是否有任何匹配,并继续在之前的结果中重新运行替换,直到找不到更多匹配项。

编辑:您也可以为重复次数制作一些正则表达式,并按长度的降序运行它们。即寻找2x3x5x2然后2x3x5然后2x3,因为逐渐地你不会击中任何已被替换的东西。