你没有得到匹配的原因是你的正则表达式不匹配:
r"<([A-Za-z0-9_]+)>"
缺少逗号、引号和空格字符,< >
根据您的示例,它们都可能出现在 内部。
这个匹配:
re.search(r"< ([A-Za-z0-9_.,\"' ]+) >", txt)
还可能使您感到困惑的是,名称列表由逗号分隔,它本身可以是未转义的values的一部分。
这意味着您不能只将该字符串拆分为','
,而是需要考虑两个不同的引号字符('
和"
)以分隔字段。
所以我会使用这种方法:
- 用于
re.match
将字符串拆分为 PREFIX < NAMES > 部分,并丢弃其余部分。
- 用于
re.findall()
根据引号将名称拆分为字段
编辑:
1)根据您的第一条评论,您的数据还可以在包含换行符的前缀之前包含一个序言。的默认行为.
是匹配除换行符以外的所有内容。
来自 Pythonre
文档:
re.DOTALL
使'.'
特殊字符完全匹配任何字符,包括换行符;没有这个标志,'.'
将匹配除换行符以外的任何内容。
所以你需要用re.DOTALL
标志构造那个正则表达式。您可以通过首先编译它并传递OR
ed 标志来做到这一点:
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