我有这样的字符串:
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]* *
,将匹配直到字符串结束。然后它将回溯直到它可以匹配oz
或ml
并且将匹配1个或多个字符a-zA-Z所以它也可以匹配0.75 ozaaaaaaa
如果需要匹配,则不需要捕获组或查找。你可以匹配:
bd+(?:.d+)*s*(?:oz|ml)b
b
防止部分字匹配的字边界d+(?:.d+)*
匹配1+位数字和可选的小数部分s*(?:oz|ml)
匹配可选的空白字符和oz
或ml
b
A字边界
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)