正则表达式,用于捕获和替换模式中的数字

时间:2019-05-26 17:24:51

标签: python regex python-3.x regex-lookarounds regex-group

我想用一个新数字(比如100)替换字符串中的第三个参数。匹配的字符串始终以function开头,第一个参数为truefalse,数字为第二个参数。

                                               Expected
                    |                             |
                    v                             v
'function(true, 0, 15)'   --> 'function(true, 0, 100)'  
'function(false, 0, 23)'  --> 'function(false, 0, 100)'

我一直在阅读相关文章,但我相信我一定误解了一些正则表达式概念。下面的代码是我尝试过的,但是它总是替换整个字符串:

import re
string = 'function(true, 0, 15)'
regex = re.compile('function\([a-zA-Z]*, [0-9]*, ([0-9]*)\)')
res = re.sub(regex, '100', string)

print(res) # 100
           # Expected: function(true, 0, 100)

问题:您能否指出以上代码为什么不起作用?我将如何编写代码以达到预期效果?

3 个答案:

答案 0 :(得分:3)

由于您要替换的数字后面紧跟着一个括号),因此您可以使用此\d+(?=\s*\))正则表达式并将其替换为100或任何您想要的值。试试这些Python代码,

import re
string = 'function(true, 0, 15)'
regex = re.compile(r'\d+(?=\s*\))')
res = re.sub(regex, '100', string)

print(res)

打印

function(true, 0, 100)

此外,您的代码无法按预期运行并且将整个字符串替换为100的原因是,因为您编写正则表达式的方式与您的整个输入和re.sub相匹配函数将所有匹配项替换为第二个参数,因此所有输入都将替换为100。但是,相反,您想要的只是用100替换第三个参数,因此您编写正则表达式的方式应该只匹配第三个参数值,如下面的正则表达式演示中所示,

Regex Demo matching only what you want to replace

您的当前正则表达式与您的整个输入匹配,如下面的演示所示,

Regex Demo with your regex matching whole input

此外,如果您感觉更好并且想要匹配整个输入,然后有选择地仅替换第三个参数,则可以使用此正则表达式捕获group1中的函数名和前两个参数,就像您想要在原始正则表达式中捕获一样,

(function\([a-zA-Z]*, [0-9]*, )[0-9]*\)

并将其替换为\g<1>100),其中\g<1>引用了group1中捕获的值,并且进一步将其替换为100)

Regex Demo with full match and selected replacement

答案 1 :(得分:1)

此表达式也可能起作用:

(?:\d+)(\))

具有一个非捕获组,其中包含我们想要的数字(?:\d+),后跟一个右边界(\)),我们可以用新的数字和$1代替它。

测试

# coding=utf8
# the above tag defines encoding for this document and is for Python 2.x compatibility

import re

regex = r"(?:\d+)(\))"

test_str = "function(true, 0, 15)"

subst = "100\\1"

# You can manually specify the number of replacements by changing the 4th argument
result = re.sub(regex, subst, test_str, 0, re.MULTILINE)

if result:
    print (result)

# Note: for Python 2.7 compatibility, use ur"" to prefix the regex and u"" to prefix the test string and substitution.

Demo

答案 2 :(得分:1)

另一种方法是,您可以在比赛前打印所有内容,在比赛后打印所有内容,然后像这样打印出新结果:

regex = re.compile( '(function\([a-zA-Z]*, [0-9]*, )([0-9]*)(\))' )
res = re.sub( regex, r'\1 100\3', string )

基本上,我在期望的匹配之前和之后的文本周围加上了括号。然后我将其打印为\1(第一个匹配项)100(新文本)\3(第三个匹配项)。

之所以提出这个特殊表达式,是为了在OP特别需要仅匹配还包含前面的“ function(”部分(或其他模式)的字符串的情况下。此外,这只是OP解决方案的扩展,因此对OP来说可能更直观。