我有这个字符串:
s = u'vitamin a min. 14,053 iu/kg vitamin c 13,000iu/kg vitamin d max. 10,000\u03bc/kg copper 1mg/kg vitamin e mon 10.00iu/kg'
我想把它拆开,所以我得到[label, label2, amount, units]
。
label
是名称,vitamin c
,可以包含unicode字符label2
为min|max
,具体取决于特定字符串。amount
是列出的数字量(可以包括逗号或小数)units
可以包含unicode字符你可以看到一些边缘情况已经出现:
label2
= min
或max
(请参阅copper
和vitamin c
)。在这种情况下,正则表达式分组可以是None
。label2
被误导(请参阅vitamin e
使用mon
)理想情况下,我想要一个可以匹配单个成分的正则表达式以及一个杂乱的列表(就像我提供的那样)。
我想出了:
import re
regex = re.compile(ur'([a-z 0-9]+)(min|max|mon)?[. ]+([0-9., ]+)((?=[%])|[a-z/]+|[^\W\d_]+/[^\W\d_]+)', re.UNICODE)
re.findall(regex, s)
# [(u'vitamin a min', u'', u'14,053 ', u'iu/kg'), (u' vitamin c', u'', u'13,000', u'iu/kg'), (u' vitamin d max', u'', u'10,000', u'\u03bc/kg'), (u' copper', u'', u'1', u'mg/kg'), (u' vitamin e mon 10', u'', u'00', u'iu/kg')]
re.findall(regex, u'vitamin a min. 14,053 iu/kg')
# [(u'vitamin a min', u'', u'14,053 ', u'iu/kg')]
这几乎与一切相符,但你可以看到一些问题。
label
与min
匹配,max
和label2
无匹配。
我不喜欢硬编码(min|max|mon)
,因为可能会出现这样的情况,即单词拼写错误,并且硬编码无法捕获。
答案 0 :(得分:0)
您可以使用非贪婪匹配来处理拆分这两个标签。
但是没有办法避免硬编码第二个标签。即使没有拼写变体,您也必须至少指定(min|max)
,否则没有理由将第二个标签与第一个标签分开(可以有任意数量的单词)。因此,您可以做的最好的事情是将该列表扩展为您可以在数据中找到的任何其他变体(可能没有那么多)。
无论如何,这是一个可行的解决方案,可以使用您提供的示例数据:
>>> regex = re.compile(ur"""
... ((?:\w+\s+)+?)((?:min|max|mon)\.?)?
... ([0-9., ]+)(%|[^\W\d_]+/[^\W\d_]+)
... """, re.X | re.I | re.U)
>>> pprint(regex.findall(s))
[(u'vitamin a ', u'min.', u' 14,053 ', u'iu/kg'),
(u'vitamin c ', u'', u'13,000', u'iu/kg'),
(u'vitamin d ', u'max.', u' 10,000', u'\u03bc/kg'),
(u'copper ', u'', u'1', u'mg/kg'),
(u'vitamin e ', u'mon', u' 10.00', u'iu/kg')]