Reputation: 17144
I have a string of following types:
a1 = 'images1subimages1/folder100/hello1.png'
a1 = 'images1subimages1 folder100 hello1.png'
a1 = 'images1subimages1folder100hello1.png'
a1 = 'images1b100d1.png'
The first Integer of the string is num0
and we only care about it. We want to increase all occurrence of num0
by one and keep other numbers the same.
Required:
a2 = 'images2subimages2/folder100/hello2.png'
a2 = 'images2subimages2 folder100 hello2.png'
a2 = 'images2subimages2folder100hello2.png'
a2 = 'images2b100d2.png'
My attempt:
import re
a1 = 'images1subimages1/folder100/hello1.png'
nums = list(map(int, re.findall(r'\d+', a1)))
nums0 = nums[0]
nums_changed = [j+1 if j==nums[0] else j for i,j in enumerate(nums)]
parts = re.findall(r'(\w*\d+)',a1)
for i in range(len(parts)):
num_parts = list(map(int, re.findall(r'\d+', parts[i])))
for num_part in num_parts:
if num_part == nums0:
parts[i] = parts[i].replace(str(nums0), str(nums0+1))
ans = '/'.join(parts)
ans
This has the following result:
a1 = 'images1subimages1/folder100/hello1.png' # good
a1 = 'images1subimages1 folder100 hello1.png' # bad
Is there a general way to solve the problem using regex in python?
Upvotes: 1
Views: 941
Reputation: 3860
Alas, I'm not as fast as some of these regex gurus. Here is my solution anyway.
re.search(r'\d+', st).group(0)
(?<!\d)+' + re.escape(first) + r'(?!\d)+
.import re
def increment_all_of_first_occurring_number(st):
first = re.search(r'\d+', st).group(0)
return re.sub(
r'(?<!\d)+' + re.escape(first) + r'(?!\d)+',
str(int(first) + 1),
st
)
if __name__ == '__main__':
a1 = 'images1subimages1/folder100/hello1.png'
a2 = 'images1subimages1 folder100 hello1.png'
a3 = 'images1subimages1folder100hello1.png'
a4 = 'images1b100d1.png'
b1 = 'images10subimages10/folder10101/hello10.png'
b2 = 'images10subimages10 folder10101 hello10.png'
b3 = 'images10subimages10folder10101hello10.png'
b4 = 'images10b10101d10.png'
print(increment_all_of_first_occurring_number(a1))
print(increment_all_of_first_occurring_number(a2))
print(increment_all_of_first_occurring_number(a3))
print(increment_all_of_first_occurring_number(a4))
print(increment_all_of_first_occurring_number(b1))
print(increment_all_of_first_occurring_number(b2))
print(increment_all_of_first_occurring_number(b3))
print(increment_all_of_first_occurring_number(b4))
Results
images2subimages2/folder100/hello2.png
images2subimages2 folder100 hello2.png
images2subimages2folder100hello2.png
images2b100d2.png
images11subimages11/folder10101/hello11.png
images11subimages11 folder10101 hello11.png
images11subimages11folder10101hello11.png
images11b10101d11.png
Upvotes: 1
Reputation: 24232
You can split the string on numbers, increment the ones equal to the first one, and rebuild the string:
import re
def increment_first(s):
parts = re.split(r'(\d+)', s)
nums = list(map(int, parts[1::2]))
num0 = nums[0]
nums = [num + (num == num0) for num in nums]
parts[1::2] = map(str, nums)
return ''.join(parts)
Testing it on your data:
tests = ['images1subimages1/folder100/hello1.png',
'images1subimages1 folder100 hello1.png',
'images1subimages1folder100hello1.png',
'images1b100d1.png']
for test in tests:
print(test, increment_first(test))
Output:
images1subimages1/folder100/hello1.png images2subimages2/folder100/hello2.png
images1subimages1 folder100 hello1.png images2subimages2 folder100 hello2.png
images1subimages1folder100hello1.png images2subimages2folder100hello2.png
images1b100d1.png images2b100d2.png
Upvotes: 1
Reputation: 626748
Ì suggest first extracting the first number and then increment all occurrences of this number when it is not enclosed with other digits with re.sub
:
import re
a1 = 'images1subimages1/folder100/hello1.png'
num0_m = re.search(r'\d+', a1) # Extract the first chunk of 1+ digits
if num0_m: # If there is a match
rx = r'(?<!\d){}(?!\d)'.format(num0_m.group()) # Set a regex to match the number when not inside other digits
print(re.sub(rx, lambda x: str(int(x.group())+1), a1)) # Increment the matched numbers
# => images2subimages2/folder100/hello2.png
See the Python demo
Upvotes: 3