HappyPy
HappyPy

Reputation: 10697

Replace part of string using a regular expression

s = 'scores:start:4.2.1.3.4.3:final:55.34.13.63.44.34'

I'm trying to reset the start scores to 0.0.0.0.0.0 so that it reads

scores:start:0.0.0.0.0.0:final:55.34.13.63.44.34

This works:

re.sub('start\:(\d+\.\d+\.\d+\.\d+\.\d+\.\d+)','0.0.0.0.0.0',s)

But I was looking for something more flexible to use in case the amount of scores change.

EDIT: Actually my example does not work, because start is removed from the string

scores:0.0.0.0.0.0:final:55.34.13.63.44.34

but I would like to keep it:

scores:start:0.0.0.0.0.0:final:55.34.13.63.44.34

Upvotes: 3

Views: 177

Answers (4)

The fourth bird
The fourth bird

Reputation: 163217

A variant using the regex PyPi module:

(?:\bstart:|\G(?!^))\.?\K\d+

The pattern matches

  • (?: Non capture group
    • \bstart: Match start:
    • | Or
    • \G(?!^) Assert the position at the end of the previous match, not at the start of the string
  • ) Close the non capture group
  • \.?\K Match an optional dot, clear the current match buffer (forget what is matched so far)
  • \d+ Match 1 or more digits (to be replaced with a 0)

Regex demo

import regex

s = 'scores:start:4.2.1.3.4.3:final:55.34.13.63.44.34'
pattern = r"(?:\bstart:|\G(?!^))\.?\K\d+"
print(regex.sub(pattern, '0', s))

Output

scores:start:0.0.0.0.0.0:final:55.34.13.63.44.34

Upvotes: 0

Kelly Bundy
Kelly Bundy

Reputation: 27588

Could replace all numbers before final with a zero:

re.sub(r'\d+(?=.*final)', '0', s)

Try it online!

Or perhaps more efficient if there were many more scores:

re.sub(r'\d|(final.*)', lambda m: m[1] or '0', s)

Upvotes: 2

dawg
dawg

Reputation: 103754

Another lambda in re.sub:

import re 
s = 'scores:start:4.2.1.3.4.3:final:55.34.13.63.44.34'
pat=r'(?<=:start:)([\d.]+)(?=:final:)'

>>> re.sub(pat, lambda m: '.'.join(['0']*len(m.group(1).split('.'))), s)
scores:start:0.0.0.0.0.0:final:55.34.13.63.44.34

Upvotes: 1

anubhava
anubhava

Reputation: 784998

You may use this re.sub with a lambda if you want to replace dot seperated numbers with same number of zeroes:

>>> import re
>>> s = 'scores:start:4.2.1.3.4.3:final:55.34.13.63.44.34'
>>> re.sub(r'start:\d+(?:\.\d+)+', lambda m: re.sub(r'\d+', '0', m.group()), s)
'scores:start:0.0.0.0.0.0:final:55.34.13.63.44.34'

We are using regex as start:\d+(?:\.\d+)+ to match text that starts with start: and followed by digits separated by dot.

In lambda part we replace each 1+ digit with 0 to get same number of zeroes in output as the input.

Upvotes: 3

Related Questions