Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ember.js/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python正则表达式,用于解析版本字符串和查找固定宽度后的内容_Python_Regex_Lookbehind_Negative Lookbehind - Fatal编程技术网

Python正则表达式,用于解析版本字符串和查找固定宽度后的内容

Python正则表达式,用于解析版本字符串和查找固定宽度后的内容,python,regex,lookbehind,negative-lookbehind,Python,Regex,Lookbehind,Negative Lookbehind,我正试图编写一个Python库来解析我们的版本格式字符串。(简化)版本字符串格式如下: -…[-alpha | beta | rc[.]][.centos | redhat | win][.snb | ivb] 这是: 产品,即foo 数字版本,即:0.1.0 [可选]预发布信息,即:beta,rc.1,alpha.extrainfo [可选]操作系统,即:centos [可选]平台,即:snb,ivb 因此,以下是有效的版本字符串: 1) foo-1.2.3 2) foo-2.3.4-al

我正试图编写一个Python库来解析我们的版本格式字符串。(简化)版本字符串格式如下:

-…[-alpha | beta | rc[.]][.centos | redhat | win][.snb | ivb]

这是:

  • 产品,即
    foo
  • 数字版本,即:
    0.1.0
  • [可选]预发布信息,即:
    beta
    rc.1
    alpha.extrainfo
  • [可选]操作系统,即:
    centos
  • [可选]平台,即:
    snb
    ivb
因此,以下是有效的版本字符串:

1) foo-1.2.3
2) foo-2.3.4-alpha
3) foo-3.4.5-rc.2
4) foo-4.5.6-rc.2.extra
5) withos-5.6.7.centos
6) osandextra-7.8.9-rc.extra.redhat
7) all-4.4.4-rc.1.extra.centos.ivb
对于所有这些示例,以下正则表达式都适用:

^(?P<prod>\w+)-(?P<maj>\d).(?P<min>\d).(?P<bug>\d)(?:-(?P<pre>alpha|beta|rc)(?:\.(?P<pre_n>\d))?(?:\.(?P<pre_x>\w+))?)?(?:\.(?P<os>centos|redhat|win))?(?:\.(?P<plat>snb|ivb))?$
^(?P<prod>\w+)-(?P<maj>\d)\.(?P<min>\d)\.(?P<bug>\d)(?:-(?P<pre>alpha|beta|rc)(?:\.(?P<pre_n>\d))?(?:\.(?:(?!centos|redhat)\w)+)?)?(?:\.(?P<os>centos|redhat))?(?:\.(?P<plat>snb|ivb))?$
使用上述正则表达式,对于字符串#8,
redhat
将在预发布的额外信息
pre#x
中拾取,而不是在
os
组中拾取

我尝试使用look-behind来避免在
pre\u x
中选择操作系统或平台字符串:

^(?P<prod>\w+)-(?P<maj>\d).(?P<min>\d).(?P<bug>\d)(?:-(?P<pre>alpha|beta|rc)(?:\.(?P<pre_n>\d))?(?:\.(?P<pre_x>\w+))?(?<!centos|redhat|win|ivb|snb))?(?:\.(?P<os>centos|redhat|win))?(?:\.(?P<plat>snb|ivb))?$
…(:\。(?P\w+))(?
即:

(?\P\w+)-(?P\d)(?P\d)(?P\d)(?:-(?帕尔法?贝塔?rc)(?:\(?P\d))?(?:\(?P\w+))(?centos?redhat?win)(?Psnb?ivb))$
如果Python的标准模块可以接受可变宽度的look back,这将很好。我宁愿尝试使用标准模块,而不是使用,因为我的库很可能被分发到大量的机器上,我希望在这些机器上限制依赖性

我也研究过类似的问题:,而且不适用

关于如何实现这一点有什么想法吗

我的regex101链接:


[对于那些感兴趣的人,这是我实际使用的完整正则表达式:

您需要使用否定的前瞻断言来使
(?p\w+
匹配除
centos
redhat
之外的任何正则表达式

('foo-1.2.3', {'version': ['1', '2', '3'], 'name': 'foo'})
('foo-2.3.4-alpha', {'version': ['2', '3', '4'], 'name': 'foo', 'extra': ['alpha']})
('foo-3.4.5-rc.2', {'version': ['3', '4', '5'], 'name': 'foo', 'extra': ['rc', '2']})
('foo-4.5.6-rc.2.extra', {'version': ['4', '5', '6'], 'name': 'foo', 'extra': ['rc', '2', 'extra']})
('withos-5.6.7.centos', {'version': ['5', '6', '7', 'centos'], 'name': 'withos'})
('osandextra-7.8.9-rc.extra.redhat', {'version': ['7', '8', '9'], 'os': 'redhat', 'name': 'osandextra', 'extra': ['rc', 'extra']})
('all-4.4.4-rc.1.extra.centos.ivb', {'platform': 'ivb', 'version': ['4', '4', '4'], 'os': 'centos', 'name': 'all', 'extra': ['rc', '1', 'extra']})
('issue-0.1.0-beta.redhat.snb', {'platform': 'snb', 'version': ['0', '1', '0'], 'os': 'redhat', 'name': 'issue', 'extra': ['beta']})
(P\d)(P\d)(P\d)(r.)$

事实上,我会避免使用正则表达式,因为它看起来已经很糟糕了,而且你告诉我们它只是简化了。手工解析它更容易阅读:

结果:


将正则表达式转换为使用lookaheads有什么帮助吗?是的,我不介意使用lookaheads,我只想坚持使用正则表达式和标准的
re
模块。TBH,我无法将其转换为lookaheads。这很容易!!感谢很多挑剔的@Avinash Raj?它不应该是\d+,在maj/min/bug中吗?我按照演示中的链接说-foo-3.4.15-rc.2不匹配。(早期发布和快速发布!;-)版本号可以是两位数(如果不是3?:-)并不难。谢谢,这看起来确实更简洁,但如果你开始增加复杂性,它很快就会变得脏兮兮的:即:扩展以允许更灵活的版本格式,如
foo_1.2.3
foo.1.2.3
foo.1.2.3
,甚至缺少bug修复:
foo-1.2
(=
foo-1.2.0
)…继续对每个令牌执行此操作,您将得到大量代码,甚至比正则表达式更难调试
^(?P<prod>\w+)-(?P<maj>\d)\.(?P<min>\d)\.(?P<bug>\d)(?:-(?P<pre>alpha|beta|rc)(?:\.(?P<pre_n>\d))?(?:\.(?:(?!centos|redhat)\w)+)?)?(?:\.(?P<os>centos|redhat))?(?:\.(?P<plat>snb|ivb))?$
def extract(text):
    parts = text.split('-')
    ret = {}
    ret['name'] = parts.pop(0)
    ret['version'] = parts.pop(0).split('.')

    if len(parts) > 0:
        rest_parts = parts.pop(0).split('.')
        if rest_parts[-1] in ['snb', 'ivb']:
            ret['platform'] = rest_parts.pop(-1)
        if rest_parts[-1] in ['redhat', 'centos', 'win']:
            ret['os'] = rest_parts.pop(-1)
        ret['extra'] = rest_parts

    return ret

tests = \
[
    'foo-1.2.3',
    'foo-2.3.4-alpha',
    'foo-3.4.5-rc.2',
    'foo-4.5.6-rc.2.extra',
    'withos-5.6.7.centos',
    'osandextra-7.8.9-rc.extra.redhat',
    'all-4.4.4-rc.1.extra.centos.ivb',
    'issue-0.1.0-beta.redhat.snb',
]

for test in tests:
    print(test, extract(test))
('foo-1.2.3', {'version': ['1', '2', '3'], 'name': 'foo'})
('foo-2.3.4-alpha', {'version': ['2', '3', '4'], 'name': 'foo', 'extra': ['alpha']})
('foo-3.4.5-rc.2', {'version': ['3', '4', '5'], 'name': 'foo', 'extra': ['rc', '2']})
('foo-4.5.6-rc.2.extra', {'version': ['4', '5', '6'], 'name': 'foo', 'extra': ['rc', '2', 'extra']})
('withos-5.6.7.centos', {'version': ['5', '6', '7', 'centos'], 'name': 'withos'})
('osandextra-7.8.9-rc.extra.redhat', {'version': ['7', '8', '9'], 'os': 'redhat', 'name': 'osandextra', 'extra': ['rc', 'extra']})
('all-4.4.4-rc.1.extra.centos.ivb', {'platform': 'ivb', 'version': ['4', '4', '4'], 'os': 'centos', 'name': 'all', 'extra': ['rc', '1', 'extra']})
('issue-0.1.0-beta.redhat.snb', {'platform': 'snb', 'version': ['0', '1', '0'], 'os': 'redhat', 'name': 'issue', 'extra': ['beta']})