使用正则表达式提取特定单词前的数字

Use regular expression to extract numbers before specific words

目标

提取单词 hourshourdaydays

之前的数字
  1. 如何使用|来匹配单词?
s = '2 Approximately 5.1 hours 100 ays 1 s'
re.findall(r"([\d.+-/]+)\s*[days|hours]", s) # note I do not know whether string s contains hours or days

return

['5.1', '100', '1']

由于 100 和 1 不在确切的单词小时之前,因此它们不应出现。预计

5.1
  1. 如何从匹配结果中提取第一个数字
s1 = '2 Approximately 10.2 +/- 30hours'
re.findall(r"([\d. +-/]+)\s*hours|\s*hours", s)

return

['10.2 +/- 30']

期待

10.2

请注意,特殊字符 +/-. 是可选的。当出现.1.3时,1.3需要和.一起出现。但是当1 +/- 0.5发生时,需要提取1并且应该提取+/-中的none。

我知道我可能会做一个拆分然后取第一个数字

str(re.findall(r"([\d. +-/]+)\s*hours", s1)[0]).split(" ")[1]

给予

'10.2'

但有些结果只有return一个数字,所以拆分会导致错误。我应该用另一步完成还是可以一步完成?

请注意,这些字符串 s1s2 是数据框中的值。因此,需要使用 applylambda 等函数进行迭代。

事实上,我会在这里使用re.findall

units = ["hours", "hour", "days", "day"]   # the order matters here: put plurals first
regex = r'(?:' + '|'.join(units) + r')'
s = '2 Approximately 5.1 hours 100 ays 1 s'
values = re.findall(r'\b(\d+(?:\.\d+)?)\s+' + regex, s)
print(values)  # prints [('5.1')]

如果你想捕获正在使用的单位,然后进行单位交替捕获,即使用:

regex = r'(' + '|'.join(units) + r')'

那么输出将是:

[('5.1', 'hours')]

代码

import re
units = '|'.join(["hours", "hour", "hrs", "days", "day", "minutes", "minute", "min"])  # possible units
number = '\d+[.,]?\d*'                              # pattern for number
plus_minus = '\+\/\-'                               # plus minus

cases = fr'({number})(?:[\s\d\-\+\/]*)(?:{units})'

pattern = re.compile(cases)  

测试

print(pattern.findall('2 Approximately 5.1 hours 100 ays 1 s'))   
# Output: [5.1]

print(pattern.findall('2 Approximately 10.2 +/- 30hours'))        
# Output: ['10.2']

print(pattern.findall('The mean half-life for Cetuximab is 114 hours (range 75-188 hours).'))        
# Output: ['114', '75']

print(pattern.findall('102 +/- 30 hours in individuals with rheumatoid arthritis and 68 hours in healthy adults.'))        
# Output: ['102', '68']

print(pattern.findall("102 +/- 30 hrs"))                          
# Output: ['102']

print(pattern.findall("102-130 hrs"))                             
# Output: ['102']

print(pattern.findall("102hrs"))                                  
# Output: ['102']

print(pattern.findall("102 hours"))                               
# Output: ['102']

说明

上面使用原始字符串 (r'...') 和字符串插值 f'...' 可以组合起来的便利:

fr'...'

PEP 498

案例字符串:

fr'({number})(?:[\s\d\-\+\/]*)(?:{units})'

零件顺序:

  • fr'({number})' - 捕获组 '(\d+[.,]?\d*)' 用于整数或浮点数
  • r'(?:[\s\d-+/]*)' - 数字和单位之间允许的字符的非捕获组(即 space、+、-、数字、/)
  • fr'(?:{units})' - 单位的非捕获组