【问题标题】:regex | extract numbers preceded by defined strings正则表达式 |提取前面定义的字符串的数字
【发布时间】:2021-10-27 15:25:45
【问题描述】:

我有这样的字符串:

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]

您可以看到我想要的输出与我从脚本中得到的不匹配。我认为我的正则表达式代码正在选择第一个数值和我定义的前瞻之间的所有内容,但是我只想要前瞻之前的最后一个数值。

我对正则表达式的理解不够。有人可以帮助解决这个问题。 谢谢!

【问题讨论】:

  • [0-9]+.*[0-9]* 中,将. 替换为\.. 表示任何字符\. 表示句号。

标签: python-3.x regex


【解决方案1】:

对您的正则表达式进行尽可能少的更改,这样您就知道自己做错了什么: 在[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]

不过,您根本不需要使用前瞻,因为您还想匹配单位。做吧

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

这给出了相同的结果:

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

【讨论】:

    【解决方案2】:

    关于您尝试的模式的一些说明:

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

    如果您想要匹配项,则不需要捕获组或环视。你可以匹配:

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

    Regex demo

    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"\b\d+(?:\.\d+)*\s*(?:{look_ahead})\b")
    
    print(size_and_units)
    

    输出

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

    【讨论】:

      【解决方案3】:

      我认为正则表达式对你有用。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-12-05
        • 2022-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-10
        • 1970-01-01
        相关资源
        最近更新 更多