0

I have strings that may include numbers in square brackets. If they do I'd like to increment up the number in the final set of square brackets up by one.

old_content='Some text\t\t[1.00]\nSome other text'

So far i have code that does that, but doesn't feel pythonic.

open_indexes = [i for i, c in enumerate(old_content) if c == "["]
close_indexes = [i for i, c in enumerate(old_content) if c == "]"]
start       = old_content[:open_indexes[-1]+1]
end         = old_content[close_indexes[-1]:]
num         = old_content[open_indexes[-1]+1:close_indexes[-1]]
num         = float(num)+1
new_content =start +str(num) + end

Is there a more pythonic way of doing this?

2 Answers 2

2

Using regex

Using the sub function of the re module, you can pass a function as the replacement:

import re

old_content = 'Some text\t\t[1.00]\nSome other text[3.00]'

def add_one_to_match(match):
    num = float(match[1])
    return f"[{num + 1}]"

new_content = re.sub(r'\[([^]]*)\][^[]*$', add_one_to_match, old_content)
print(repr(new_content))

Using string functions

You can double-partition the string from the right (to take only the last occurrence):

old_content = 'Some text\t\t[1.00]\nSome other text[3.00]'

start, _, end = old_content.rpartition('[')
num, _, end = end.rpartition(']')
print(repr(f"{start}[{float(num)+1}]{end}"))

Both ways will give:

'Some text\t\t[1.00]\nSome other text[4.0]'
Sign up to request clarification or add additional context in comments.

4 Comments

That doesn't increment the first number, because of the $ not matching before the second [.
The regex pattern \[(.*?)] with a lazy ? quantifier will do the job for both numbers.
@mportes but OP doesn't want both. Only the last...
@mportes By the way using a negated group (\[([^]]*)\]) is more efficient then using a lazy quantifier
1

Split the string into 3 parts: pre, number, post using re.findall. Increment the number by 1, and join the parts back into a single string.

import re
old_content = 'Some text\t\t[1.00]\nSome other text'
matches = list(re.findall(r"(.*\[)(.*)(\].*)", old_content, re.S)[0])
matches[1] = str(float(matches[1]) + 1)
new_content = "".join(matches)
print(new_content)
# Some text               [2.0]
# Some other text

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.