【问题标题】:Regex match in PythonPython中的正则表达式匹配
【发布时间】:2017-01-05 10:14:53
【问题描述】:

我有一个这样的正则表达式

r"^(.*?),(.*?)(,.*?=.*)"

还有这样的字符串

name1,value1,tag11=value11,tag12=value12,tag13=value13

我正在尝试使用正则表达式检查字符串是否遵循以下格式:name,value,名称和值对以逗号分隔。

然后我需要使用正则表达式提取逗号分隔的数据。

我将数据提取为第一组作为 name1,第二组作为 value2,第三组从 tag11 到 value13 完全匹配(由于贪婪匹配)。

但我想匹配每个名称和值对。我是 Python 新手,不知道如何实现这一点。

【问题讨论】:

  • 你能发布你的代码吗?
  • 像下面这样的正则表达式可能会有所帮助:((?<name>\w+),(?<value>\w+))|(?<name>\w+)=(?<value>\w+)(在没有命名捕获组的 RegExr 上测试)。

标签: python regex


【解决方案1】:

事实证明,与 .NET 不同,Python 不支持重复命名的捕获组,这有点可惜(这意味着我的解决方案比我想象的要长一些)。这符合您的要求吗?

import re

def is_valid(s):
    pattern = '^name\d+,value\d+(,tag\d+=value\d+)*$'
    return re.match(pattern, s)

def get_name_value_pairs(s):
    if not is_valid(s):
        raise ValueError('Invalid input: {}'.format(s))

    pattern = '((?P<name1>\w+),(?P<value1>\w+))|(?P<name2>\w+)=(?P<value2>\w+)'
    for match in re.finditer(pattern, s):
        name1 = match.group('name1')
        name2 = match.group('name2')
        value1 = match.group('value1')
        value2 = match.group('value2')

        if name1 and value1:
            yield name1, value1
        elif name2 and value2:
            yield name2, value2

if __name__ == '__main__':
    testString = 'name1,value1,tag11=value11,tag12=value12,tag13=value13'
    assert not is_valid('')
    assert not is_valid('foo')
    assert is_valid(testString)

    print(list(get_name_value_pairs(testString)))

输出

[('name1', 'value1'), ('tag11', 'value11'), ('tag12', 'value12'), ('tag13', 'value13')]

编辑 1

添加了输入验证逻辑。假设:

  • 必须具有name&lt;x&gt;,value&lt;x&gt; 形式的初始名称/值对
  • 以下所有对必须采用tag&lt;x&gt;=value&lt;x&gt; 形式
  • 名称和值仅由字母数字字符组成
  • 不允许有空格

请注意,我目前没有验证 x 是否是名称/值对中的相同值,我认为这是一项要求。我不知道该怎么做把这个留给读者练习。

【讨论】:

  • 您的解决方案对我有帮助,但我需要验证字符串的格式。它的格式应为 name1、value1、tag-1=value-1、tag-2=value-2 ... tag-n=value-n。我怎样才能做到这一点。
  • @MohanRaj 我添加了验证逻辑。我真的不明白你在做什么,所以我假设了究竟是什么决定了一个字符串是否有效,但我已经列出了我的假设,你可以根据需要进行调整。
【解决方案2】:

为什么不用逗号分开:

s = 'name1,value1,tag11=value11,tag12=value12,tag13=value13'
print(s.split(','))

如果你想使用正则表达式,使用模式也很简单:

[^,]+

例子:

https://regex101.com/r/jS6fgW/1

【讨论】:

    【解决方案3】:

    首先,验证格式 acc。到您的模式,然后使用 [,=] 正则表达式(匹配 ,=)拆分并转换为这样的字典:

    import itertools, re
    s = 'name1,value1,tag11=value11,tag12=value12,tag13=value13'
    if re.match(r'[^,=]+,[^,=]+(?:,[^,=]+=[^,=]+)+$', s):
        l = re.split("[=,]", s)
        d = dict(itertools.izip_longest(*[iter(l)] * 2, fillvalue=""))
        print(d)
    else:
        print("Not valid!")
    

    Python demo

    pattern

    ^[^,=]+,[^,=]+(?:,[^,=]+=[^,=]+)+$
    

    详情

    • ^ - 字符串的开头(在 re.match 中,可以省略,因为模式已经锚定)
    • [^,=]+ - 除=, 之外的1+ 个字符
    • , - 逗号
    • [^,=]+ - 除=, 之外的1+ 个字符
    • (?:,[^,=]+=[^,=]+)+ - 1 个或多个序列:
      • , - 逗号
      • [^,=]+ - 除=, 之外的1+ 个字符
      • = - 等号
      • [^,=]+ - 除=, 之外的1+ 个字符
    • $ - 字符串结束。

    【讨论】:

    • 它对我有帮助,但我还需要验证输入字符串的格式。它的格式应为 name1、value1、tag-1=value-1、tag-2=value-2 ... tag-n=value-n。我怎样才能做到这一点。
    • 您需要精确:逗号分隔的name,value 可以出现在字符串内部的某处,还是出现在字符串的末尾?也许^(?:\w+[=,]\w+)+$ 就够了,而且可以吗?或者,如果您在开头确实有一个逗号分隔的名称值,然后是 = 分隔的名称,请使用 ^[^,=]+,[^,=]+(?:,[^,=]+=[^,=]+)+$
    • 应该只在字符串的开头。
    猜你喜欢
    • 2016-07-01
    • 2013-09-22
    • 1970-01-01
    • 2022-12-11
    • 2015-09-14
    • 2021-12-31
    • 2018-12-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多