python - 正则表达式以在 Python 中以未知的出现顺序捕获不同的元素

标签 python regex string string-matching regex-lookarounds

我正在构建一个正则表达式以从 Python 中的转发电子邮件中提取 header 值。我只对这些标题在电子邮件中的第一次出现感兴趣,我只想捕获出现在冒号之后的文本部分。

From: ...  
Sent: ...   
To: ...   
Subject: ...  

对于上述格式的大多数变体,以下正则表达式使用 re.search 可以正常工作:

(?:From\s*:\s*)(.*)(?:\n*)(?:Sent\s*:\s*)(.*)(?:\n*)(?:To\s*:\s*)(.*)(?:\n*)(?:Subject\s*:\s*)

但有时,不同的标题部分顺序不同并且缺少元素,如下所示:

Sent: ...    
From: ...  
Subject: ... 

我想我可以使用正向前瞻来以任何顺序匹配标题格式,但我无法让它工作。有谁知道如何有效地完成这项工作?非常感谢任何帮助。

最佳答案

一种可能性是永远不使用任何字符,并使用前瞻性来捕获可选组中所需的所有内容:

(?=(?:.*^From\s*:\s*)(.*?$)|)(?=(?:.*^Sent\s*:\s*)(.*?$)|)(?=(?:.*^To\s*:\s*)(.*?$)|)(?=(?:.*^Subject\s*:\s*)(.*?$)|)

https://regex101.com/r/pOThDP/2

间隔开,这只是类似模式的 4 次重复,看起来像:

(?=(?:.*^From\s*:\s*)(.*?$)|)
(?=(?:.*^Sent\s*:\s*)(.*?$)|)
(?=(?:.*^To\s*:\s*)(.*?$)|)
(?=(?:.*^Subject\s*:\s*)(.*?$)|)

此外,为了清楚起见,您可能会考虑命名捕获组:

(?=(?:.*^From\s*:\s*)(?P<From>.*?$)|)(?=(?:.*^Sent\s*:\s*)(?P<Sent>.*?$)|)(?=(?:.*^To\s*:\s*)(?P<To>.*?$)|)(?=(?:.*^Subject\s*:\s*)(?P<Subject>.*?$)|)

https://regex101.com/r/pOThDP/3

编辑:python 代码示例:

text = '''To: totext
Sent: sent text
this text has no no "from" label
Subject: subject text'''
pattern = re.compile(r'(?=(?:.*^From\s*:\s*)(.*?$)|)(?=(?:.*^Sent\s*:\s*)(.*?$)|)(?=(?:.*^To\s*:\s*)(.*?$)|)(?=(?:.*^Subject\s*:\s*)(.*?$)|)', flags=re.S | re.M)
match = re.search(pattern, text)
print(match.groups())

输出是:

(None, 'sent text', 'totext', 'subject text')

关于python - 正则表达式以在 Python 中以未知的出现顺序捕获不同的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51818807/

相关文章:

string - 如何将 char* 转换为 D 中的字符串?

ios - 使用 NSURLConnection 返回超大字符串的正确方法是什么?

python - Django:部署到 ElasticBeanstalk myapp.settings 上导入错误

python - 多个轴的单个图例

python - 属性错误 : module 'tensorflow' has no attribute 'get_variable'

javascript - 查找包含 "//"的字符串并从 "//"替换到末尾

python - 使用 QScintilla 和 PyQt 的自动完成建议中没有 python 关键字

java - 联合与否定,Java RegEx

Java 正则表达式转义字符

java - 我在扫描字符串时遇到问题