【问题标题】:Regex to extract both integer or float values followed by a unit, Python正则表达式提取整数或浮点值,后跟一个单位,Python
【发布时间】:2019-12-05 19:32:51
【问题描述】:

我想构建一个正则表达式,它捕获字符串中的所有模式,其中在测量单位(ml、mg、kg 等)之前存在整数或浮点数。我当前的正则表达式只考虑整数并在有空格时中断。我想在我的代码中处理这些。

p = re.compile('[0-9](?:mg|kg|ml|q.s.|ui|M|g|µg)')
x = '0.9mg is the approximate dosage'
z = p.findall(x)
print(z)

这不适用于小数,并且在有空格时也会中断。

要捕获的预期模式是:

Examples: 0.9 mg, 9 mg, 9mg, 0.9mg

有关此的任何帮助

在代码中使用正则表达式:

mg = []
newregex = r"[0-9\.\s]+(?:mg|kg|ml|q.s.|ui|M|g|µg)" 
for s in zz:
    for e in extracteddata:
        v = re.search(newregex,extracteddata,flags=re.IGNORECASE|re.MULTILINE)
        if v:
            mg.append(v.group(0))

【问题讨论】:

    标签: python regex python-3.x


    【解决方案1】:

    你可以试试这个:

    ([.\d]+)\s*(?:mg|kg|ml|q.s.|ui|M|g|µg)
    

    Try it online.

    【讨论】:

    • 谢谢。我正在尝试将匹配的模式保存在列表中,但出现错误“ValueError:无法使用已编译模式处理标志参数”。如果你能帮我解决它,那就太好了。在问题中添加代码以供参考。
    • 从字符串模式中提取的实际数字可以通过.group(1)获取。所以试试mg.append(re.search(newregex,extracteddata,flags=re.IGNORECASE|re.MULTILINE)).group(1)。此外,将模式从循环内部移动到循环外部也是一个好主意,这样就不必每次都编译它。
    • 我试过了,但它不起作用。我已经对代码进行了一些更改,现在在v = re.search(newregex,extracteddata,flags=re.IGNORECASE|re.MULTILINE) 行中获得了“TypeError:预期的字符串或类似字节的对象”。对此有任何想法
    • 没有.group(0),而是.group(1)
    • 你说的是我之前贴的代码吗? mg.append(re.search(newregex,extracteddata,flags=re.IGNORECASE|re.MULTILINE)) 在哪里?
    【解决方案2】:

    (?<!\d|\.)\d+(?:\.\d+)?\s*?(?:mg|kg|ml|q\.s\.|ui|M|g|µg)(?!\w)

    此正则表达式将选择格式正确的数字,其后带有正确格式的单位,并将拒绝格式错误的数字或不存在的单位。

    • (?<!\d|\.) - 确保此数字之前没有数字或小数点。
    • \d+ - 获得一位或多位数字。
    • (?:\.\d+)? - 可选择获取小数点,后跟一位或多位数字。
    • \s*? - 获得零到无限的空白字符,尽可能少。
    • (?:mg|kg|ml|q\.s\.|ui|M|g|µg) - 捕获列出的单位之一。
    • (?!\w) - 确保在捕获的单元之后没有额外的数据。

    Regex demo


    import re
    
    p = re.compile('(?<!\d|\.)\d+(?:\.\d+)?\s*?(?:mg|kg|ml|q\.s\.|ui|M|g|µg)(?!\w)')
    x = 'Examples: 0.9 mg, 9 mg, 9mg, 0.9mg'
    
    print(p.findall(x))
    

    ['0.9mg', '9mg', '9mg', '0.9mg']

    Python demo

    【讨论】:

    • 谢谢。我正在尝试将匹配的模式保存在列表中,但出现错误“ValueError:无法使用已编译模式处理标志参数”。如果你能帮我解决它,那就太好了。在问题中添加代码以供参考。
    • @techsmart 这个错误是说你必须把re.IGNORECASE|re.MULTILINE 标志放到你的re.compile 语句中,而不是你的re.search 语句中。
    【解决方案3】:

    试试这个:

    x = '9mg 9.0mg  0 mg .009 mg is the approximate dosage'
    p = re.compile('[0-9\.\s]+(?:mg|kg|ml|q.s.|ui|M|g|µg)')
    p.findall(x)
    

    输出

    ['9mg', ' 9.0mg', '  0 mg', ' .009 mg']
    

    【讨论】:

    • 如果字符串中 0.9 和 mg 之间有空格,则它不起作用。示例:“x = 0.9 mg 是近似剂量”
    • 谢谢。我正在尝试将匹配的模式保存在列表中,但出现错误“ValueError:无法使用已编译模式处理标志参数”。如果你能帮我解决它,那就太好了。在问题中添加代码以供参考。
    • @techsmart 您需要在变量中输出['9mg', ' 9.0mg', ' 0 mg', ' .009 mg'] 吗?然后你可以做z = p.findall(x)。此外,如果您执行re.search,那么您需要对对象执行.group(0)。最好是findallfinditer
    • 不,实际上我不需要所有匹配项。我已经更新了上面的代码,现在在 v = re.search(newregex,extracteddata,flags=re.IGNORECASE|re.MULTILINE) 行中得到“TypeError:预期的字符串或类似字节的对象”。对此有任何想法
    【解决方案4】:

    此答案不仅是对该问题的特定解决方案,而且是尝试将字符串与数字匹配的一般解决方案,带或不带precision,带或不带units,带或不带thousand 分隔符European (.,)International (.,) 格式

    (((\d{4,}(?:[\.,]\d+)?)|((\d{1,3}(?:((\.)|,)\d{1,3})?(?:\6\d{1,3})*(?:(?(7),|\.)\d+)?)))\s*(?:[a-zA-Z]*))

    • \d{1,3} - 选择一到三位数字。
    • \d{4,} - 选择一到三位数字。
    • ((\.)|,) - 选择 . (European), (International) 作为千位分隔符。
    • \6 - 只选择以前匹配的千位分隔符。
    • (?(7),|\.) - if-else 条件匹配精度分隔符 , (European). (International) 基于先前匹配的千位分隔符。
    • \s*?(?:[a-zA-Z]+) - 在匹配的数字后面选择一个单位,带或不带前面的空格字符。

    Regex Demo


    import re
    
    p = re.compile('(((\d{4,}(?:[\.,]\d+)?)|((\d{1,3}(?:((\.)|,)\d{1,3})?(?:\6\d{1,3})*(?:(?(7),|\.)\d+)?)))\s*(?:[a-zA-Z]*))')
    x = 'Examples: 0.9 mg, 9 mg, 9mg, 0.9mg'
    
    print([item[0]for item in p.findall(x)])
    

    输出['0.9 mg', '9 mg', '9mg', '0.9mg']

    Python Demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      • 2014-05-18
      • 2018-06-20
      相关资源
      最近更新 更多