regex |提取前面有定义字符串的数字



我有这样的字符串:

Bla bla 0.75 oz. Bottle
Mugs, 8oz. White
Bowls, 4.4" dia x 2.5", 12ml. Natural
Ala bala 3.3" 30ml Bottle'

我想提取出现在我的预定义前的数值,在本例中是[oz, ml]

0.75 oz
8 oz
12 ml
30 ml

我有以下代码:

import re
import pandas as pd
look_ahead = "oz|ml"
s = pd.Series(['Bla bla 0.75 oz. Bottle',
'Mugs, 8oz. White',
'Bowls, 4.4" dia x 2.5", 12ml. Natural',
'Ala bala 3.3" 30ml Bottle'])
size_and_units = s.str.findall(
rf"((?!,)[0-9]+.*[0-9]* *(?={look_ahead})[a-zA-Z]+)")
print(size_and_units)

输出如下:

0                  [0.75 oz]
1                      [8oz]
2    [4.4" dia x 2.5", 12ml]
3                [3.3" 30ml]

你可以看到我想要的输出和我从脚本中得到的不匹配。我认为我的regex代码是选择第一个数值和我定义的前瞻性之间的一切,但我只希望在我的前瞻性的最后一个数值。

我是我的深度为正则表达式。有人能帮忙解决这个问题吗?谢谢你!

尽可能少的改变你的正则表达式,所以你知道你做错了什么:在[0-9]+.*[0-9]*中用.代替..表示任何字符.表示句号。

s = pd.Series(['Bla bla 0.75 oz. Bottle',
'Mugs, 8oz. White',
'Bowls, 4.4" dia x 2.5", 12ml. Natural',
'Ala bala 3.3" 30ml Bottle'])
size_and_units = s.str.findall(
rf"((?!,)[0-9]+.*[0-9]* *(?={look_ahead})[a-zA-Z]+)")

给:

0    [0.75 oz]
1        [8oz]
2       [12ml]
3       [30ml]

你根本不需要使用forward,因为你也想匹配单位。只做

d+.*d*s*(?:oz|ml)

给出相同的结果:

size_and_units = s.str.findall(
rf"d+.*d*s*(?:{look_ahead})")

关于您尝试的模式的一些注意事项:

  • 你可以省略前面的(?!,),因为它总是为真,因为你开始下一个匹配的数字
  • 在本部分.*[0-9]* *(?=oz|ml)[a-zA-Z]+)这是可选的.*[0-9]* *,将匹配直到字符串结束。然后它将回溯直到它可以匹配ozml并且将匹配1个或多个字符a-zA-Z所以它也可以匹配0.75 ozaaaaaaa

如果需要匹配,则不需要捕获组或查找。你可以匹配:

bd+(?:.d+)*s*(?:oz|ml)b
  • b防止部分字匹配的字边界
  • d+(?:.d+)*匹配1+位数字和可选的小数部分
  • s*(?:oz|ml)匹配可选的空白字符和ozml
  • bA字边界

Regex演示

import pandas as pd
look_ahead = "oz|ml"
s = pd.Series(['Bla bla 0.75 oz. Bottle',
'Mugs, 8oz. White',
'Bowls, 4.4" dia x 2.5", 12ml. Natural',
'Ala bala 3.3" 30ml Bottle'])
size_and_units = s.str.findall(
rf"bd+(?:.d+)*s*(?:{look_ahead})b")
print(size_and_units)

输出
0    [0.75 oz]
1        [8oz]
2       [12ml]
3       [30ml]

我认为regex表达式将为您工作。

[0-9]+.*[0-9]* *(oz|ml)

最新更新