来自 PCRE REGEXP 的 MySQL REGEXP_REPLACE 翻译

Posted

技术标签:

【中文标题】来自 PCRE REGEXP 的 MySQL REGEXP_REPLACE 翻译【英文标题】:MySQL REGEXP_REPLACE translation from PCRE REGEXP 【发布时间】:2021-01-07 11:48:29 【问题描述】:

我正在尝试提取字符串的体积字段以按数字排序。


给定以下数据:

    300 毫升的东西 300毫升的东西 一些特别的东西(300 毫升) 8-v 不应该匹配的东西

第一次尝试: 只需将字符串转换为unsigned(在此线程中找到:reference)

问题:显然也会考虑到第 4 个数据示例。


第二次尝试:使用REGEXP_REPLACE提取值(在此线程中找到:reference)

CAST(
    REGEXP_REPLACE(
        LOWER(column),
        "[:digit:]+[:space:]*ml",
        "///"
    ) as UNSIGNED
) AS volume

...使用manual 中定义的character_classes。

问题:character_classes 似乎没有按预期工作(可能是空格的字符类名称有问题?)。


第三次尝试:使用常见的正则表达式标记

CAST(
    REGEXP_REPLACE(
        LOWER(column),
        "\d+\s*ml",
        "///"
    ) as UNSIGNED
) AS volume

...这似乎效果更好。

问题:它也再次匹配了第4个数据示例。


问题:我如何在 mysql REGEXP_REPLACE 中执行某种正向前瞻,它只会匹配数据示例 1-3(由于强制转换为较低而忽略大小写敏感)?

我尝试过的那个似乎在 PCRE(带有全局标志)中工作正常,但在 MySQL 中却不行:

^.*\d+\s*ml.*$(忽略丢失的捕获组)

翻译如下:匹配所有内容,直到 1 个或多个数字,后跟 0 个或多个空格,并找到字符串 ml

【问题讨论】:

毫升和兆升? 8.0 使用\d; 8.0 之前使用 [:digit:]。等等。 【参考方案1】:

问题在于将替换结果转换为无符号的组合。

使用后:

REGEXP_SUBSTR(
    LOWER(article.name),
    "[:digit:]+[:space:]*ml"
) AS volume

而不是 REGEXP_REPLACE 并删除无符号转换(不管双括号或单括号以某种方式),REGEXP 工作正常。

【讨论】:

【参考方案2】:

试试这个:

       CAST(
          REGEXP_SUBSTR( 
                LOWER(@c), 
                "([[:digit:]]+)[[:space:]]*ml" )
          AS UNSIGNED)  AS VOLUME;

出于您的目的,您肯定需要 REGEX_SUBSTR() 而不是 REGEX_REPLACE()。

我已经在 MySQL 8 和 MariaDB 10.3 - 10.5 上进行了尝试。无论如何,对我来说,需要将括号 [[:digit:]] 加倍。如果您使用较旧的\s 表示法,则需要将\ 转义字符加倍:\\s+

(MariaDb's implementation of REGEX_SUBSTR() 不接受optional parameters that MySQL's does。

我不得不说,在医疗保健 IT 部门工作过,将正则表达式与药物剂量结合起来让我感到害怕。当心!测试!测试!如果你有病人,他们会感谢你的。

【讨论】:

因为这基本上是我所做的,我会接受你的回答 ;-) 仅供参考:这不是为了医疗保健,而是为了化学(基础研究):-p

以上是关于来自 PCRE REGEXP 的 MySQL REGEXP_REPLACE 翻译的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式(RegExp)

Lua ngx.re.find options参数

Lua ngx.re.find options参数

Sword pcre库使用

正则表达式-Python实现

强烈推荐!Python 这个宝藏库 re 正则匹配