【问题标题】:How do i extract a list of elements encased in quotation marks bounded by <> and delimited by commas - python, regex?如何提取以<>为界并以逗号分隔的引号中的元素列表-python,正则表达式?
【发布时间】:2013-08-06 17:11:06
【问题描述】:

给定这样的字符串:

ORTH < "cali.ber,kl", 'calf' , "done" >,\nLKEYS.KEYREL.PRED "_calf_n_1_rel", 

使用正则表达式,我如何获得如下所示的元组:

('ORTH', ['cali.ber,kl','calf','done'])

我一直这样做:

txt = '''ORTH < "cali.ber,kl", 'calf' , "done" >,'''
e1 = txt.partition(" ")[0]
vs = re.search(r"<([A-Za-z0-9_]+)>", txt)
v = vs.group(1)
v1 = [i[1:-1] for i in vs.strip().strip("<>").split(",")]
print v1

但是re.search().group(1) 我没有得到任何消息。应该怎么做才能得到想要的输出?

【问题讨论】:

    标签: python regex string brackets


    【解决方案1】:

    你没有得到匹配的原因是你的正则表达式不匹配:

    r"&lt;([A-Za-z0-9_]+)&gt;" 缺少逗号、引号和空格字符,根据您的示例,这些都可能出现在 &lt; &gt; 内。

    这个匹配:

    re.search(r"< ([A-Za-z0-9_.,\"' ]+) >", txt)
    

    还有一点可能让您感到困惑的是,名称列表是用逗号分隔的,它本身可以是 values 的一部分,未转义。

    这意味着您不能只用',' 拆分该字符串,而是需要考虑两个不同的引号字符('")来分隔字段。

    所以我会使用这种方法:

    • 使用re.match 将字符串拆分为PREFIX 部分,并丢弃其余部分。
    • 使用re.findall()根据引号将名称拆分为字段

    编辑:

    1)根据您的第一条评论,您的数据还可以在包含换行符的前缀之前包含一个序言. 的默认行为是 to match everything except newlines

    来自 Python re 文档:

    re.DOTALL

    使'.' 特殊字符完全匹配任何字符,包括换行符;如果没有这个标志,'.' 将匹配除换行符以外的任何内容。

    因此,您需要使用 re.DOTALL 标志构造该正则表达式。为此,您首先编译它并传递ORed 标志:

    re.compile(pattern, flags=re.DOTALL)
    

    2) 如果您在正则表达式中包含PREFIX 之前的空格字符,它将仅匹配实际包含该空格的数据 - 但不再匹配您的第一条示例数据。所以我使用.*?([A-Z\.]*)... 来涵盖这两种情况。 ? 用于非贪婪匹配,因此它匹配可能最短的匹配而不是最长的匹配。

    3) 要覆盖PREFIX.FOO,只需将前缀模式扩展为([A-Z\.]*),方法是包含. 字符并将其转义。

    更新的示例涵盖了您提到的所有案例:

    import re
    
    TEST_VALUES = [
        """ORTH.FOO < "cali.ber,kl", 'calf' , "done" >,\nLKEYS.KEYREL.PRED "_calf_n_1_rel",""",
        """calf_n1 := n_-_c_le & n_-_pn_le &\n [ ORTH.FOO < "cali.ber,kl", 'calf' , "done" >,\nLKEYS.KEYREL.PRED "_calf_n_1_rel","""
    ]
    
    EXPECTED = ('ORTH.FOO', ['cali.ber,kl','calf','done'])
    
    
    pattern = re.compile(r'.*?([A-Z\.]*) < (.*) >.*', flags=re.DOTALL)
    
    
    for value in TEST_VALUES:
        prefix, names_str = pattern.match(value).groups()
        names = re.findall('[\'"](.*?)["\']', names_str)
    
        result = prefix, names
        assert(result == EXPECTED)
    
    print result
    

    【讨论】:

    • 谢谢,正则表达式适用于上面给定的字符串,但它不适用于我的数据,因为我在前缀之前有一些其他字符,例如"""calf_n1 := n_-_c_le &amp; n_-_pn_le &amp;\n [ ORTH &lt; "cali.ber,kl", 'calf' , "done" &gt;,\nLKEYS.KEYREL.PRED "_calf_n_1_rel","""。我试图用r'.* ([A-Z]*) &lt; (.*) &gt;.*' 捕捉这种模式,但它也不起作用 =(
    • 有时我的数据也会给出"""calf_n1 := n_-_c_le &amp; n_-_pn_le &amp;\n [ PHON.POO "whatever",\n ORTH &lt; "cali.ber,kl", 'calf' , "done" &gt;,\nLKEYS.KEYREL.PRED "_calf_n_1_rel","""...
    • 我不介意在(prefix, name_str) 中找到('PHON.POO', 'whatever'),但我似乎无法获得CAPS.PREFIX &lt; 'x', "y"&gt;
    • @2er0 更新了我的答案以涵盖您提供的其他案例。
    • 感谢re.DOTALL 标志的作用 =)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多