正则表达式以匹配 YAML 中的键

新手上路,请多包涵

我有一个看起来像这样的 yaml..!用户可以定义 N 个 xyz_flovor_id 其中 _flovor_id 密钥将是通用的。目的是获取 *_flavor_id 键并从中提取值。

   server:
    tenant: "admin"
    availability_zone: "nova"
    cpu_overcommit_ratio: 1:1
    memory_overcommit_ratio: 1:1
    xyz_flovor_id: 1
    abc_flavor_id: 2

我能够计算出匹配 _flovor_id 的正则表达式。然而,当试图在代码中使用它时,它会抛出错误。这是我的代码。

 def get_flavor_keys(params):
    pattern = re.compile(r'[^*]flavor_id')
    for key, value in params.iteritems():
        print value
        if key == 'server':
            if pattern.match(value):
                print 'test'

print value 正在转储整个 YAML 文件(预期)。之后立即回溯。

 Traceback (most recent call last):
  File "resource_meter.py", line 150, in <module>
    get_flavor_keys(items)
  File "resource_meter.py", line 15, in get_flavor_keys
    if pattern.match(value):
TypeError: expected string or buffer

原文由 tgcloud 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
2 个回答

你需要这个正则表达式。我将它分组为键值对:

 ^\s*(?P<key>\w+_flavor_id):\s*(?P<value>\d+)

Python 演示: https ://repl.it/Lk5W/0

 import re

regex = r"^\s*(?P<key>\w+_flavor_id):\s*(?P<value>\d+)"

test_str = ("  server:\n"
    "    tenant: \"admin\"\n"
    "    availability_zone: \"nova\"\n"
    "    cpu_overcommit_ratio: 1:1\n"
    "    memory_overcommit_ratio: 1:1\n"
    "    xyz_flavor_id: 1\n"
    "    abc_flavor_id: 2\n")

matches = re.finditer(regex, test_str, re.MULTILINE)

for matchNum, match in enumerate(matches):
    print ("{key}:{value}".format(key = match.group('key'), value=match.group('value')))

原文由 Duc Filan 发布,翻译遵循 CC BY-SA 3.0 许可协议

您会收到该错误,因为键的值 server 不是字符串,而是字典(或字典的子类)。这就是您输入中的 YAML 映射(包括密钥 abc_flavor_id )加载的内容。

除此之外,使用正则表达式来解析 YAML(或任何其他结构化文本格式,如 HTML、XML、CVS)始终不是一个好主意,因为即使不是不可能,也很难捕获语法的所有细微差别。如果不是,您将不需要解析器。

例如,对文件的一个小改动,只是添加一个注释,说明哪些值需要为编辑文件的用户更新,打破了简单的正则表达式方法:

 server:
  tenant: "admin"
  availability_zone: "nova"
  cpu_overcommit_ratio: 1:1
  memory_overcommit_ratio: 1:1
  xyz_flovor_id: 1
  abc_flavor_id:  # extract the value for this key
    2

上面的 YAML documenta 在语义上与您的相同,但将不再适用于当前发布的其他答案。

如果某些 YAML 加载/保存操作将您的输入转换为(再次在语义上等效):

 server: {abc_flavor_id: 2, availability_zone: nova,
  cpu_overcommit_ratio: 61, memory_overcommit_ratio: 61,
  tenant: admin, xyz_flovor_id: 1} then tweaking a dumb regular expression will not begin to suffice (this is not a construed example, this is the default way to dump your data structure in PyYAML and in ruamel.yaml using 'safe'-mode).

您需要做的是,正则表达式匹配与 server 关联的值的键,而不是整个文档:

 import re
import sys
from ruamel.yaml import YAML

yaml_str = """\
server:
  tenant: "admin"
  availability_zone: "nova"
  cpu_overcommit_ratio: 1:1
  memory_overcommit_ratio: 1:1
  xyz_flovor_id: 1
  abc_flavor_id:  # extract the value for this key
    2
"""

def get_flavor_keys(params):
    pattern = re.compile(r'(?P<key>.*)_flavor_id')
    ret_val = {}
    for key in params['server']:
        m = pattern.match(key)
        if m is not None:
            ret_val[m.group('key')] = params['server'][key]
            print('test', m.group('key'))
    return ret_val

yaml = YAML(typ='safe')
data = yaml.load(yaml_str)
keys = get_flavor_keys(data)
print(keys)

这给你:

 {'abc': 2}

xyz_flovor_id 当然不匹配,但也许这是您帖子中的错字)。

原文由 Anthon 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题