2

我得到了这个代码:

myString = 'blabla123_01_version6688_01_01Long_stringWithNumbers'
versionSplit = re.findall(r'-?\d+|[a-zA-Z!@#$%^&*()_+.,<>{}]+|\W+?', myString)

for i in reversed(versionSplit):
    id = versionSplit.index(i)
    if i.isdigit():
        digit = '%0'+str(len(i))+'d'
        i = int(i) + 1
        i = digit % i
        versionSplit[id]=str(i)
        break

final = ''
myString = final.join(versionSplit)
print myString

假设只增加给定字符串的最后一位数字。但是,如果您运行该代码,您会看到如果字符串中的数字与最后一个数字相同,如果您继续运行脚本,它将一个接一个地增加它。谁能帮我找出原因?

预先感谢您的任何帮助

4

4 回答 4

8

您是否有理由不这样做:

prefix, version = re.match(r"(.*[^\d]+)([\d]+)$", myString).groups()
newstring = prefix + str(int(version)+1).rjust(len(version), '0')

笔记:

  • 这实际上会正确地“继承”版本号: ("09" -> "10") 和 ("99" -> "100")
  • 此正则表达式假定在最后的最终版本子字符串之前至少有一个非数字字符。如果这不匹配,它将抛出一个AttributeError. 您可以对其进行重组以引发更合适或更具体的异常(例如,如果re.match(...)返回None;请参阅下面的评论以获取更多信息)。

相应调整。

于 2012-04-13T03:08:28.797 回答
2

问题在于第 5 行的函数的使用。这会返回列表中第一次list.index()出现的值的索引,从左到右,但代码正在遍历反向列表(从右到左)。有很多方法可以解决这个问题,但这里有一个对现有代码所做的更改最少的方法:反向迭代索引(避免反转列表)。

for idx in range(len(versionSplit)-1, -1, -1):
    i = versionSplit[idx]
    if chunk.isdigit():
        digit = '%0'+str(len(i))+'d'
        i = int(i) + 1
        i = digit % i
        versionSplit[idx]=str(i)
        break
于 2012-04-13T03:05:11.037 回答
1
myString = 'blabla123_01_version6688_01_01veryLong_stringWithNumbers01'
versionSplit = re.findall(r'-?\d+|[^\-\d]+', myString)

for i in xrange(len(versionSplit) - 1, -1, -1):
    s = versionSplit[i]
    if s.isdigit():
        n = int(s) + 1
        versionSplit[i] = "%0*d" % (len(s), n)
        break

myString = ''.join(versionSplit)
print myString

笔记:

  • .index()使用方法来尝试查找字符串是愚蠢的。只需使用递减索引来尝试versionSplit. 正如上面@David Robinson 所评论的那样,这就是您的问题所在。

  • 不要id用作变量名;您正在掩盖内置功能id()

  • 此代码使用*格式模板,它将接受整数并设置宽度。

  • 我简化了模式:要么匹配数字(带有可选的前导减号),要么匹配非数字。

  • 我对此进行了测试,它似乎有效。

于 2012-04-13T03:13:25.283 回答
1

首先,三个注意事项:

  1. id是 Python 的保留字;
  2. 对于加入,一个更 Pythonic 的习惯用法是''.join(),使用文字空字符串
  3. reversed()返回一个迭代器,而不是一个列表。这就是为什么我使用list(reversed()), 以便rev.index(i)以后做。

更正的代码:

import re

myString = 'blabla123_01_version6688_01_01veryLong_stringWithNumbers01'
print myString
versionSplit = re.findall(r'-?\d+|[a-zA-Z!@#$%^&*()_+.,<>{}]+|\W+?', myString)

rev = list(reversed(versionSplit))  # create a reversed list to work with from now on

for i in rev:
    idd = rev.index(i)
    if i.isdigit():
        digit = '%0'+str(len(i))+'d'
        i = int(i) + 1
        i = digit % i
        rev[idd]=str(i)
        break

myString = ''.join(reversed(rev))  # reverse again only just before joining
print myString
于 2012-04-13T03:19:00.497 回答