Documentation Home

12.8.2 正则表达式

表 12.14 正则表达式函数和运算符

姓名 描述
NOT REGEXP REGEXP 的否定
REGEXP 字符串是否匹配正则表达式
REGEXP_INSTR() 子串匹配正则表达式的起始索引
REGEXP_LIKE() 字符串是否匹配正则表达式
REGEXP_REPLACE() 替换匹配正则表达式的子字符串
REGEXP_SUBSTR() 返回匹配正则表达式的子串
RLIKE 字符串是否匹配正则表达式

正则表达式是一种为复杂搜索指定模式的强大方法。本节讨论可用于正则表达式匹配的函数和运算符,并通过示例说明一些可用于正则表达式运算的特殊字符和结构。另见第 3.3.4.7 节,“模式匹配”

MySQL 使用 Unicode 国际组件 (ICU) 实现正则表达式支持,它提供完整的 Unicode 支持并且是多字节安全的。(在 MySQL 8.0.4 之前,MySQL 使用 Henry Spencer 的正则表达式实现,它以字节方式运行并且不是多字节安全的。有关使用正则表达式的应用程序可能受实现更改影响的方式的信息,请参阅正则表达式兼容性注意事项。)

在 MySQL 8.0.22 之前,可以对这些函数使用二进制字符串参数,但它们会产生不一致的结果。在 MySQL 8.0.22 及更高版本中,拒绝将二进制字符串与任何 MySQL 正则表达式函数一起使用 ER_CHARACTER_SET_MISMATCH

正则表达式函数和运算符说明

  • expr NOT REGEXP pat, expr NOT RLIKE pat

    这与. NOT (expr REGEXP pat)

  • expr REGEXP pat, expr RLIKE pat

    expr 如果字符串与 pattern 指定的正则表达式匹配,则 返回 1 pat,否则返回 0。如果 exprpatNULL,则返回值为NULL

    REGEXP并且 RLIKE是 的同义词REGEXP_LIKE()

    有关匹配如何发生的其他信息,请参阅 的说明 REGEXP_LIKE()

    mysql> SELECT 'Michael!' REGEXP '.*';
    +------------------------+
    | 'Michael!' REGEXP '.*' |
    +------------------------+
    |                      1 |
    +------------------------+
    mysql> SELECT 'new*\n*line' REGEXP 'new\\*.\\*line';
    +---------------------------------------+
    | 'new*\n*line' REGEXP 'new\\*.\\*line' |
    +---------------------------------------+
    |                                     0 |
    +---------------------------------------+
    mysql> SELECT 'a' REGEXP '^[a-d]';
    +---------------------+
    | 'a' REGEXP '^[a-d]' |
    +---------------------+
    |                   1 |
    +---------------------+
  • REGEXP_INSTR(expr, pat[, pos[, occurrence[, return_option[, match_type]]]])

    expr返回与 pattern 指定的正则表达式匹配的 字符串的子字符串的起始索引, pat如果没有匹配则返回 0。如果 exprpatNULL,则返回值为NULL。字符索引从 1 开始。

    REGEXP_INSTR()采用这些可选参数:

    • pos: expr开始搜索的位置。如果省略,默认值为 1。

    • occurrence:要搜索的匹配项。如果省略,默认值为 1。

    • return_option: 返回哪种类型的位置。如果此值为 0,则 REGEXP_INSTR()返回匹配的子字符串的第一个字符的位置。如果此值为 1,则 REGEXP_INSTR()返回匹配子字符串之后的位置。如果省略,则默认为 0。

    • match_type:指定如何执行匹配的字符串。含义如对 所述 REGEXP_LIKE()

    有关匹配如何发生的其他信息,请参阅 的说明 REGEXP_LIKE()

    mysql> SELECT REGEXP_INSTR('dog cat dog', 'dog');
    +------------------------------------+
    | REGEXP_INSTR('dog cat dog', 'dog') |
    +------------------------------------+
    |                                  1 |
    +------------------------------------+
    mysql> SELECT REGEXP_INSTR('dog cat dog', 'dog', 2);
    +---------------------------------------+
    | REGEXP_INSTR('dog cat dog', 'dog', 2) |
    +---------------------------------------+
    |                                     9 |
    +---------------------------------------+
    mysql> SELECT REGEXP_INSTR('aa aaa aaaa', 'a{2}');
    +-------------------------------------+
    | REGEXP_INSTR('aa aaa aaaa', 'a{2}') |
    +-------------------------------------+
    |                                   1 |
    +-------------------------------------+
    mysql> SELECT REGEXP_INSTR('aa aaa aaaa', 'a{4}');
    +-------------------------------------+
    | REGEXP_INSTR('aa aaa aaaa', 'a{4}') |
    +-------------------------------------+
    |                                   8 |
    +-------------------------------------+
  • REGEXP_LIKE(expr, pat[, match_type])

    expr 如果字符串与 pattern 指定的正则表达式匹配,则 返回 1 pat,否则返回 0。如果 exprpatNULL,则返回值为NULL

    该模式可以是一个扩展的正则表达式,其语法在 正则表达式语法中讨论。模式不必是文字字符串。例如,它可以指定为字符串表达式或表列。

    可选match_type 参数是一个字符串,可以包含以下任何或所有指定如何执行匹配的字符:

    • c: 区分大小写匹配。

    • i: 不区分大小写的匹配。

    • m: 多行模式。识别字符串中的行终止符。默认行为是仅在字符串表达式的开头和结尾匹配行终止符。

    • n:. 字符匹配行终止符。默认是 .匹配停止在一行的末尾。

    • u: Unix-only 行结尾。只有换行符被识别为以 、 和匹配运算符结尾.^$

    如果在 中指定了指定相互矛盾的选项的字符match_type,则最右边的优先。

    默认情况下,正则表达式操作 在确定字符类型和执行比较时使用expr和 参数的字符集和排序规则。pat如果参数具有不同的字符集或排序规则,则适用强制性规则,如 第 10.8.4 节,“表达式中的排序规则强制性”中所述。可以使用显式排序规则指示符指定参数以更改比较行为。

    mysql> SELECT REGEXP_LIKE('CamelCase', 'CAMELCASE');
    +---------------------------------------+
    | REGEXP_LIKE('CamelCase', 'CAMELCASE') |
    +---------------------------------------+
    |                                     1 |
    +---------------------------------------+
    mysql> SELECT REGEXP_LIKE('CamelCase', 'CAMELCASE' COLLATE utf8mb4_0900_as_cs);
    +------------------------------------------------------------------+
    | REGEXP_LIKE('CamelCase', 'CAMELCASE' COLLATE utf8mb4_0900_as_cs) |
    +------------------------------------------------------------------+
    |                                                                0 |
    +------------------------------------------------------------------+

    match_type可以用ci 字符指定以覆盖默认的区分大小写。例外:如果任一参数是二进制字符串,则参数将以区分大小写的方式作为二进制字符串处理,即使match_type 包含该i字符也是如此。

    笔记

    MySQL 在字符串中使用 C 转义语法(例如, \n表示换行符)。如果您希望您的 expror pat参数包含 literal \,则必须将其加倍。(除非 NO_BACKSLASH_ESCAPES 启用了 SQL 模式,在这种情况下不使用转义字符。)

    mysql> SELECT REGEXP_LIKE('Michael!', '.*');
    +-------------------------------+
    | REGEXP_LIKE('Michael!', '.*') |
    +-------------------------------+
    |                             1 |
    +-------------------------------+
    mysql> SELECT REGEXP_LIKE('new*\n*line', 'new\\*.\\*line');
    +----------------------------------------------+
    | REGEXP_LIKE('new*\n*line', 'new\\*.\\*line') |
    +----------------------------------------------+
    |                                            0 |
    +----------------------------------------------+
    mysql> SELECT REGEXP_LIKE('a', '^[a-d]');
    +----------------------------+
    | REGEXP_LIKE('a', '^[a-d]') |
    +----------------------------+
    |                          1 |
    +----------------------------+
    mysql> SELECT REGEXP_LIKE('abc', 'ABC');
    +---------------------------+
    | REGEXP_LIKE('abc', 'ABC') |
    +---------------------------+
    |                         1 |
    +---------------------------+
    mysql> SELECT REGEXP_LIKE('abc', 'ABC', 'c');
    +--------------------------------+
    | REGEXP_LIKE('abc', 'ABC', 'c') |
    +--------------------------------+
    |                              0 |
    +--------------------------------+
  • REGEXP_REPLACE(expr, pat, repl[, pos[, occurrence[, match_type]]])

    用替换字符串替换字符串 中 expr与模式指定的正则表达式匹配的匹配 项,并返回结果字符串。如果、 或 是 ,则返回值为 。 patreplexprpatreplNULLNULL

    REGEXP_REPLACE()采用这些可选参数:

    • pos: expr开始搜索的位置。如果省略,默认值为 1。

    • occurrence:要替换的匹配项。如果省略,默认值为 0(表示替换所有出现的地方”)。

    • match_type:指定如何执行匹配的字符串。含义如对 所述 REGEXP_LIKE()

    MySQL 8.0.17之前,该函数返回的结果使用UTF-16字符集;MySQL 8.0.17及以后版本,使用匹配搜索表达式的字符集和排序规则。(缺陷 #94203,缺陷 #29308212)

    有关匹配如何发生的其他信息,请参阅 的说明 REGEXP_LIKE()

    mysql> SELECT REGEXP_REPLACE('a b c', 'b', 'X');
    +-----------------------------------+
    | REGEXP_REPLACE('a b c', 'b', 'X') |
    +-----------------------------------+
    | a X c                             |
    +-----------------------------------+
    mysql> SELECT REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3);
    +----------------------------------------------------+
    | REGEXP_REPLACE('abc def ghi', '[a-z]+', 'X', 1, 3) |
    +----------------------------------------------------+
    | abc def X                                          |
    +----------------------------------------------------+
  • REGEXP_SUBSTR(expr, pat[, pos[, occurrence[, match_type]]])

    如果没有匹配项,则返回expr与 pattern 指定的正则表达式匹配的 字符串的子字符串 。如果或 是,则返回值为。 patNULLexprpatNULLNULL

    REGEXP_SUBSTR()采用这些可选参数:

    • pos: expr开始搜索的位置。如果省略,默认值为 1。

    • occurrence:要搜索的匹配项。如果省略,默认值为 1。

    • match_type:指定如何执行匹配的字符串。含义如对 所述 REGEXP_LIKE()

    MySQL 8.0.17之前,该函数返回的结果使用UTF-16字符集;MySQL 8.0.17及以后版本,使用匹配搜索表达式的字符集和排序规则。(缺陷 #94203,缺陷 #29308212)

    有关匹配如何发生的其他信息,请参阅 的说明 REGEXP_LIKE()

    mysql> SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+');
    +----------------------------------------+
    | REGEXP_SUBSTR('abc def ghi', '[a-z]+') |
    +----------------------------------------+
    | abc                                    |
    +----------------------------------------+
    mysql> SELECT REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3);
    +----------------------------------------------+
    | REGEXP_SUBSTR('abc def ghi', '[a-z]+', 1, 3) |
    +----------------------------------------------+
    | ghi                                          |
    +----------------------------------------------+

正则表达式语法

正则表达式描述一组字符串。最简单的正则表达式是其中没有特殊字符的正则表达式。例如,正则表达式 hello匹配hello,仅此而已。

非平凡的正则表达式使用某些特殊的结构,以便它们可以匹配多个字符串。例如,正则表达式hello|world包含 |交替运算符并匹配helloor world

作为一个更复杂的示例,正​​则表达式 B[an]*s匹配任何字符串 BananasBaaaaasBs,以及任何其他以 a 开头 B、以 an 结尾并且中间s包含任意数量的an字符的字符串。

下面的列表涵盖了一些可以在正则表达式中使用的基本特殊字符和结构。有关用于实现正则表达式支持的 ICU 库支持的完整正则表达式语法的信息,请访问 Unicode 网站的国际组件

  • ^

    匹配字符串的开头。

    mysql> SELECT REGEXP_LIKE('fo\nfo', '^fo$');                   -> 0
    mysql> SELECT REGEXP_LIKE('fofo', '^fo');                      -> 1
  • $

    匹配字符串的结尾。

    mysql> SELECT REGEXP_LIKE('fo\no', '^fo\no$');                 -> 1
    mysql> SELECT REGEXP_LIKE('fo\no', '^fo$');                    -> 0
  • .

    匹配任何字符(包括回车符和换行符,尽管要在字符串中间匹配这些字符,必须给出m(多行)匹配控制字符或(?m) 模式内修饰符)。

    mysql> SELECT REGEXP_LIKE('fofo', '^f.*$');                    -> 1
    mysql> SELECT REGEXP_LIKE('fo\r\nfo', '^f.*$');                -> 0
    mysql> SELECT REGEXP_LIKE('fo\r\nfo', '^f.*$', 'm');           -> 1
    mysql> SELECT REGEXP_LIKE('fo\r\nfo', '(?m)^f.*$');           -> 1
  • a*

    匹配零个或多个a 字符的任意序列。

    mysql> SELECT REGEXP_LIKE('Ban', '^Ba*n');                     -> 1
    mysql> SELECT REGEXP_LIKE('Baaan', '^Ba*n');                   -> 1
    mysql> SELECT REGEXP_LIKE('Bn', '^Ba*n');                      -> 1
  • a+

    匹配一个或多个a 字符的任意序列。

    mysql> SELECT REGEXP_LIKE('Ban', '^Ba+n');                     -> 1
    mysql> SELECT REGEXP_LIKE('Bn', '^Ba+n');                      -> 0
  • a?

    匹配零个或一个a字符。

    mysql> SELECT REGEXP_LIKE('Bn', '^Ba?n');                      -> 1
    mysql> SELECT REGEXP_LIKE('Ban', '^Ba?n');                     -> 1
    mysql> SELECT REGEXP_LIKE('Baan', '^Ba?n');                    -> 0
  • de|abc

    交替; 匹配任一序列 deabc.

    mysql> SELECT REGEXP_LIKE('pi', 'pi|apa');                     -> 1
    mysql> SELECT REGEXP_LIKE('axe', 'pi|apa');                    -> 0
    mysql> SELECT REGEXP_LIKE('apa', 'pi|apa');                    -> 1
    mysql> SELECT REGEXP_LIKE('apa', '^(pi|apa)$');                -> 1
    mysql> SELECT REGEXP_LIKE('pi', '^(pi|apa)$');                 -> 1
    mysql> SELECT REGEXP_LIKE('pix', '^(pi|apa)$');                -> 0
  • (abc)*

    匹配序列的零个或多个实例 abc

    mysql> SELECT REGEXP_LIKE('pi', '^(pi)*$');                    -> 1
    mysql> SELECT REGEXP_LIKE('pip', '^(pi)*$');                   -> 0
    mysql> SELECT REGEXP_LIKE('pipi', '^(pi)*$');                  -> 1
  • {1},{2,3}

    重复; 和 符号提供了一种更通用的编写正则表达式的方法,这些正则表达式与模式的前一个原子(或片段)的 多次出现相匹配。并且 是整数。 {n}{m,n}mn

    • a*

      可以写成a{0,}.

    • a+

      可以写成a{1,}.

    • a?

      可以写成a{0,1}.

    更准确地说, 完全 匹配. 的匹配项或多个实例 。 通过 , 包含的实例进行 匹配。如果同时 给出 和 ,则必须小于或等于 。 a{n}naa{n,}naa{m,n}mnamnmn

    mysql> SELECT REGEXP_LIKE('abcde', 'a[bcd]{2}e');              -> 0
    mysql> SELECT REGEXP_LIKE('abcde', 'a[bcd]{3}e');              -> 1
    mysql> SELECT REGEXP_LIKE('abcde', 'a[bcd]{1,10}e');           -> 1
  • [a-dX],[^a-dX]

    匹配任何字符(或不是,如果 ^使用)a, b, c, dX. -两个其他字符之间的字符形成一个范围,该范围匹配从第一个字符到第二个字符的所有字符。 例如, [0-9]匹配任何十进制数字。要包含文字]字符,它必须紧跟在左括号之后 [。要包含文字 -字符,它必须写在最前面或最后。任何在字符中没有定义的特殊含义的字符[]pair 只匹配它自己。

    mysql> SELECT REGEXP_LIKE('aXbc', '[a-dXYZ]');                 -> 1
    mysql> SELECT REGEXP_LIKE('aXbc', '^[a-dXYZ]$');               -> 0
    mysql> SELECT REGEXP_LIKE('aXbc', '^[a-dXYZ]+$');              -> 1
    mysql> SELECT REGEXP_LIKE('aXbc', '^[^a-dXYZ]+$');             -> 0
    mysql> SELECT REGEXP_LIKE('gheis', '^[^a-dXYZ]+$');            -> 1
    mysql> SELECT REGEXP_LIKE('gheisa', '^[^a-dXYZ]+$');           -> 0
  • [=character_class=]

    在括号表达式(使用 [and编写])中, [=character_class=]表示等价类。它匹配具有相同排序规则值的所有字符,包括它自己。例如,如果 o(+)是等价类的成员 [[=o=]][[=(+)=]]、 和[o(+)]都是同义词。等价类不能用作范围的端点。

  • [:character_class:]

    在括号表达式(使用 [and编写])中, [:character_class:]表示与属于该类的所有字符匹配的字符类。下表列出了标准类名。这些名称代表ctype(3)手册页中定义的字符类。特定的语言环境可能会提供其他类名。字符类不能用作范围的端点。

    字符类名称 意义
    alnum 字母数字字符
    alpha 字母字符
    blank 空白字符
    cntrl 控制字符
    digit 数字字符
    graph 图形字符
    lower 小写字母字符
    print 图形或空格字符
    punct 标点符号
    space 空格、制表符、换行符和回车
    upper 大写字母字符
    xdigit 十六进制数字字符
    mysql> SELECT REGEXP_LIKE('justalnums', '[[:alnum:]]+');       -> 1
    mysql> SELECT REGEXP_LIKE('!!', '[[:alnum:]]+');               -> 0

要在正则表达式中使用特殊字符的文字实例,请在其前面加上两个反斜杠 (\) 字符。MySQL 解析器解释其中一个反斜杠,正则表达式库解释另一个。例如,要匹配1+2包含特殊+字符的字符串,以下正则表达式中只有最后一个是正确的:

mysql> SELECT REGEXP_LIKE('1+2', '1+2');                       -> 0
mysql> SELECT REGEXP_LIKE('1+2', '1\+2');                      -> 0
mysql> SELECT REGEXP_LIKE('1+2', '1\\+2');                     -> 1

正则表达式资源控制

REGEXP_LIKE()和类似的功能使用可以通过设置系统变量来控制的资源:

  • 匹配引擎将内存用于其内部堆栈。要以字节为单位控制堆栈的最大可用内存,请设置 regexp_stack_limit系统变量。

  • 匹配引擎按步骤运行。要控制引擎执行的最大步数(从而间接控制执行时间),请设置 regexp_time_limit系统变量。因为此限制表示为步骤数,所以它只会间接影响执行时间。通常,它是毫秒级的。

正则表达式兼容性注意事项

在 MySQL 8.0.4 之前,MySQL 使用 Henry Spencer 正则表达式库来支持正则表达式操作,而不是 International Components for Unicode (ICU)。以下讨论描述了 Spencer 和 ICU 库之间可能影响应用程序的差异:

  • 对于 Spencer 库, REGEXPand RLIKE 运算符以字节方式工作,因此它们不是多字节安全的,并且可能会在多字节字符集上产生意外结果。此外,这些运算符通过字符的字节值和重音字符比较字符可能不相等,即使给定的排序规则将它们视为相等。

    ICU 具有完整的 Unicode 支持并且是多字节安全的。它的正则表达式函数将所有字符串视为 UTF-16. 您应该记住,位置索引基于 16 位块而不是代码点。这意味着,当传递给此类函数时,使用多个块的字符可能会产生意想不到的结果,如下所示:

    mysql> SELECT REGEXP_INSTR('