使用正则表达式获取拆分版本号的最佳方法

时间:2015-09-28 07:30:08

标签: python regex

我有这个字符串(它是文件的一部分):

{
    return array(
        'major'     => '1',
        'minor'     => '9',
        'revision'  => '1',
        'patch'     => '1',
        'stability' => '',
        'number'    => '',
    );
}

我需要从中形成一个正确的版本号,在本例中为“1.9.1.1”。我已经编写了这样做的代码,但我想知道是否有更好,更漂亮的解决方案,或者需要更少代码的解决方案。我一直在考虑使用一个更复杂的正则表达式来返回版本号的所有部分,但我无法弄清楚如何,并且返回像“1911”这样的匹配可能会导致比它的价值更多的麻烦 - 当有两个 - 涉及的数字,例如“1.10.1.1”。在这种情况下,不可能知道在哪里拆分“11011”,因为它可能也是“11.0.1.1”或“1.1.0.11”。

这是我所拥有的(在Python代码中):

        result = []
        result.append(re.search("'major'\\s+=>\\s+'(\\d+)'", text))
        result.append(re.search("'minor'\\s+=>\\s+'(\\d+)'", text))
        result.append(re.search("'revision'\\s+=>\\s+'(\\d+)'", text))
        result.append(re.search("'patch'\\s+=>\\s+'(\\d+)'", text))

        str = ""
        for res in result:
            if res:
                str += res.group(1) + "."

        return str[:-1]

5 个答案:

答案 0 :(得分:2)

您可以使用正则表达式捕获连续数组元素中re.findall的所有数值,然后将捕获的数字加入.

import re
s = """{
    return array(
        'major'     => '1',
        'minor'     => '9',
        'revision'  => '1',
        'patch'     => '1',
        'stability' => '',
        'number'    => '',
    );
}
"""
ptn = r"return\s+array\s*\(\s*'major'\s*=>\s*'(\d*)',\s*'minor'\s*=>\s*'(\d*)',\s*\s*'revision'\s*=>\s*'(\d*)',\s*\s*'patch'\s*=>\s*'(\d*)"
print (".".join(*re.findall(ptn, s)))

请参阅IDEONE demo

答案 1 :(得分:2)

如果您的大型源文件中始终只有一个版本信息,则使用re.findall会更加简单:

import re

s = '''{
    return array(
        'major'     => '1',
        'minor'     => '9',
        'revision'  => '1',
        'patch'     => '1',
        'stability' => '',
        'number'    => '',
    );
}'''


def get_version_number(s):
    version_fields = ('major', 'minor', 'revision', 'patch')
    version_dict = dict(re.findall(r"'(%s)'\s*=>\s*'(\d*)'" % '|'.join(version_fields), s))
    return '.'.join(version_dict.get(key, '') for key in version_fields)


if __name__ == '__main__':
    print get_version_number(s)

答案 2 :(得分:1)

我实际上非常喜欢你的代码,因为你很清楚你想要做什么。将所有内容放在一个大的正则表达式中使得理解IMO变得更加困难。你可以做些什么来清理它:

import re
s = """{
    return array(
        'major'     => '1',
        'minor'     => '9',
        'revision'  => '1',
        'patch'     => '1',
        'stability' => '',
        'number'    => '',
    );
}
"""
baseregex = "'{}'\\s+=>\\s+'(\\d+)'"
keys = 'major', 'minor', 'revision', 'patch'
result = [re.search(baseregex.format(key)) for key in keys]
print '.'.join([res.group(1) for res in result if res])

答案 3 :(得分:1)

实际上你可能不需要重新,特别是如果你订阅了现在你有两个问题哲学(http://regex.info/blog/2006-09-15/247

选中此项(s1是您的输入字符串):

clean = lambda x: x.split('=>')[1].strip().rstrip(',').strip("'") \
    if '=>' in x else ''
version = '.'.join([clean(x) for x in s1.splitlines() if clean(x)])

答案 4 :(得分:0)

你可以这样做:

import re

s = '''{
    return array(
        'major'     => '1',
        'minor'     => '9',
        'revision'  => '1',
        'patch'     => '1',
        'stability' => '',
        'number'    => '',
    );
}'''

version_list = ('major', 'minor', 'revision', 'patch')

version = []

for i in version_list:
    version.append(re.search("'(" + i + ")'\s+=>\s+'(\d)'", s).group(2))

print '.'.join(version)