查找字符串中正则表达式的所有模式



我有一个过于复杂的正则表达式,据我所知是正确的

route = r"""[s+|(][iI](.)?[vV](.)?(W|s|$)?
|s intravenously|s intravenous
|[s|(][pP](.)?[oO](.)?(W|s|$)
|s perorally|s?(per)?oral(ly)?|s intraduodenally
|[s|(]i(.)?p(.)?(W|s|$)?  
|s intraperitoneal(ly)?
|[s|(]i(.)?c(.)?v(.)?(W|s|$)? 
|s intracerebroventricular(ly)?
|[s|(][iI](.)?[gG](.)?(W|s|$)?
|s intragastric(ly)?
|[s|(]s(.)?c(.)?(W|s|$)?
|subcutaneous(ly)?(s+injection)?
|[s|(][iI](.)?[mM](.)?(W|s|$)? 
|sintramuscular
"""

使用re.search,如果它是字符串,我设法获得众多模式之一

s = 'Pharmacokinetics parameters evaluated after single IV or IM'
m = re.search(re.compile(route, re.X), s)
m.group(0)
' IV '

我在别的地方读到使用re.findall来找到所有的事件。在我的梦里,这将返回:

['IV', 'IM']

结果是:

[('',
'',
' ',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
''),
('',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'',
'')]

对于您显示的摘录:

b
(?: i 
(?: ntra
(?: cerebroventricular (?:ly)?
| duodenally
| gastric (?:ly)?
| muscular
| peritoneal (?:ly)?
| venous (?:ly)?
) b
| .? (?: [gmpv] | c .? v ) b .?
)
|
(?:per)? oral (?:ly)? b
|
p .? o b .?
|
subcutaneous (?:ly)? (?: s+ injection )? b
)

演示建议:

  • 你有一个很长的模式,你已经使用了re.X选项,这是一件好事,通过以严格和可读的方式格式化模式来最大限度地利用它。最后,使用字母顺序。这听起来可能很傻,但这确实节省了时间!也可以添加以#开头的内联注释。
  • 在两种不同的情况下,你有许多具有相同字符的字符类=>也使用全局re.I标志,并以小写书写模式。
  • 我看到你试图用s或丑陋的[s|(](你不需要在字符类中转义括号,|并不意味着它里面的or)和(W|s|$)?(这是完全无用的,因为你使它可选)来划分子字符串。忘记它,使用单词边界b(阅读它以更好地理解在哪些情况下它匹配)。
  • 使用re.findall代替或re.search,因为您希望在单个字符串中有多个匹配。
  • 使用非捕获组(?: ... )代替捕获组( ... )。(当模式包含捕获组时,re.findall只返回捕获组的内容,而不是整个匹配)。
  • 从左分解模式(从左到右测试模式,从左分解减少了要测试的分支的数量)。考虑到这一点,子模式(?:per)? oral (?:ly)? b | p .? o b .?可以这样重写:oral (?:ly)? b | p (?: eroral (?:ly)? b | .? o .?)
  • 你也可以从右边因式分解在可能的情况下。这不是一个很大的改进,但它减少了模式大小。

use (?:.)?在单词模式中找一个句号或一个句号。注意我找到了ip或ip.模式匹配不排除模式中的模式,例如ip在POip旁边。

print ("查找带或不带句点的单词组合")

data="single intravenously intravenous IV oral PO intraperitoneal intraperitoneally i.p. ip"
matches=re.findall(r'[iI](?:.)?[vV](?:.)?|intravenous(?:ly)?|[pP](?:.)?[oO](?:.)?|peroral(?:ly)?|oral(?:ly)?|[iI](?:.)?[pP](?:.)?|intraperitoneal(?:ly)?',data)
print(matches)

输出:

['intravenously', 'intravenous', 'IV', 'oral', 'PO', 'intraperitoneal', 'intraperitoneally', 'i.p.', 'ip']

最新更新