字符组有时也被称为方括号表达式(bracketed expression)。字符组有助于匹配特定字符或者特定的字符序列。它们可以像字符简写式那样代表一大批字符,比如 \d 匹配的字符与 [0-9] 所匹配的字符一样。但字符组更有针对性,因此用途比简写式更广。下面是一些字符组简单例子。
需求为找出含有十六进制数字的字符串。十六进制数字由 0-9、A-F 十六个字符构成,并且假设有三种表示形式:
set @x:=conv(54321,10,16);
insert into t_regexp(a) values
(concat('a 0x',@x,' z')),(concat('a 0X',@x,' z')),(concat('a $',@x,' z')),(concat('a $',lower(@x),' z')),(concat('a ',@x,'h z')),(concat('a ',@x,'H z')),
(concat('a 0x',@x,'h z')),(concat('a $',@x,'h z')),(concat('a $0x',@x,'h z')),(concat('a 0x$',@x,'h z')),(concat('a ^0x',@x,' z'));
\s(?i)(((0x|\$)[a-f\d]+)|([a-f\d]+h))\s
mysql> select a from t_regexp where a regexp '\\s(?i)(((0x|\\$)[a-f\\d]+)|([a-f\\d]+h))\\s';
+------------+
| a |
+------------+
| a 0xD431 z |
| a 0XD431 z |
| a $D431 z |
| a $d431 z |
| a D431h z |
| a D431H z |
+------------+
6 rows in set (0.00 sec)
可以看到查询结果包含了所有符合规则的十六进制数。
mysql> select a from t_regexp where a regexp '\\b(?i)(((0x|\\$)[a-f\\d]+)|([a-f\\d]+h))\\b';
+--------------+
| a |
+--------------+
| a 0xD431 z |
| a 0XD431 z |
| a D431h z |
| a D431H z |
| a $D431h z |
| a 0x$D431h z |
| a ^0xD431 z |
+--------------+
7 rows in set (0.00 sec)
对字符组取反会匹配与字符组内容不匹配的字符。比如,如果不想匹配元音字符,可以这样写:[^aeiou]。该字符组起始位置的脱字符(^)的意义就是:“不匹配这些字符”。脱字符必须出现在起始位置。
字符组可以像集合那样操作。不是所有的实现程序都支持这项功能,但 MySQL 支持该功能。
mysql> set @r:='[0-3[6-9]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select '1' regexp @r,'5' regexp @r, '8' regexp @r\G
*************************** 1. row ***************************
'1' regexp @r: 1
'5' regexp @r: 0
'8' regexp @r: 1
1 row in set (0.00 sec)
正则表达式处理器会匹配0到3之间的数字或者6到9之间的数字。
mysql> set @r:='[a-z&&[^m-r]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select 'a' regexp @r, 'b' regexp @r, 's' regexp @r, 'z' regexp @r, 'l' regexp @r, 'm' regexp @r, 'r' regexp @r, 'n' regexp @r\G
*************************** 1. row ***************************
'a' regexp @r: 1
'b' regexp @r: 1
's' regexp @r: 1
'z' regexp @r: 1
'l' regexp @r: 1
'm' regexp @r: 0
'r' regexp @r: 0
'n' regexp @r: 0
1 row in set (0.00 sec)
这匹配a到z之间的字符,但其中m到r之间的字符除外。
POSIX(Portable Operating System Interface,可移植操作系统接口)是 IEEE 维护的一系列标准,其中包含了一个正则表达式标准(ISO/IEC/IEEE 9945:2009)。该标准提供了一套命名的字符组,其形式为:[[:xxxx:]]。
mysql> set @r='[[:alnum:]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select '0' regexp @r, '9' regexp @r, 'a' regexp @r, 'A' regexp @r, 'z' regexp @r, 'Z' regexp @r, '\n' regexp @r, '\\n' regexp @r\G
*************************** 1. row ***************************
'0' regexp @r: 1
'9' regexp @r: 1
'a' regexp @r: 1
'A' regexp @r: 1
'z' regexp @r: 1
'Z' regexp @r: 1
'\n' regexp @r: 0
'\\n' regexp @r: 1
1 row in set (0.03 sec)
[[:alnum:]] 与简写式 \w 等价。
mysql> set @r:='[[:alpha:]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select 'a' regexp @r, 'A' regexp @r, 'z' regexp @r, 'Z' regexp @r, '0' regexp @r, '9' regexp @r\G
*************************** 1. row ***************************
'a' regexp @r: 1
'A' regexp @r: 1
'z' regexp @r: 1
'Z' regexp @r: 1
'0' regexp @r: 0
'9' regexp @r: 0
1 row in set (0.02 sec)
mysql> set @r:='[[:^alpha:]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select 'a' regexp @r, 'A' regexp @r, 'z' regexp @r, 'Z' regexp @r, '0' regexp @r, '9' regexp @r\G
*************************** 1. row ***************************
'a' regexp @r: 0
'A' regexp @r: 0
'z' regexp @r: 0
'Z' regexp @r: 0
'0' regexp @r: 1
'9' regexp @r: 1
1 row in set (0.11 sec)
mysql> set @r:='[[:space:]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select ' ' regexp @r, '\t' regexp @r, '\n' regexp @r, '\r' regexp @r;
+---------------+----------------+----------------+----------------+
| ' ' regexp @r | '\t' regexp @r | '\n' regexp @r | '\r' regexp @r |
+---------------+----------------+----------------+----------------+
| 1 | 1 | 1 | 1 |
+---------------+----------------+----------------+----------------+
1 row in set (0.00 sec)
mysql> set @r:='[[:blank:]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select ' ' regexp @r, '\t' regexp @r, '\n' regexp @r, '\r' regexp @r;
+---------------+----------------+----------------+----------------+
| ' ' regexp @r | '\t' regexp @r | '\n' regexp @r | '\r' regexp @r |
+---------------+----------------+----------------+----------------+
| 1 | 1 | 0 | 0 |
+---------------+----------------+----------------+----------------+
1 row in set (0.00 sec)
与 [[:space:]] 不同,[[:blank:]] 不包括回车、换行符。
mysql> set @r:='[[:ascii:]]';
Query OK, 0 rows affected (0.00 sec)
mysql> select char(0) regexp @r, char(1) regexp @r, char(127) regexp @r, char(128) regexp @r;
+-------------------+-------------------+---------------------+---------------------+
| char(0) regexp @r | char(1) regexp @r | char(127) regexp @r | char(128) regexp @r |
+-------------------+-------------------+---------------------+---------------------+
| 1 | 1 | 1 | 0 |
+-------------------+-------------------+---------------------+---------------------+
1 row in set (0.00 sec)
[[:ascii:]] 匹配 ascii码 0~127的字符。
下表所示为POSIX字符组。
字符组 | 描述 |
---|---|
[[:alnum:]] | 匹配字母或数字 |
[[:alpha:]] | 匹配字母 |
[[:ascii:]] | 匹配ASCII字符(共128个) |
[[:blank:]] | 匹配空白字符 |
[[:ctrl:]] | 匹配控制字符 |
[[:digit:]] | 匹配数字 |
[[:graph:]] | 匹配图形字符 |
[[:lower:]] | 匹配小写字符 |
[[:print:]] | 匹配可打印字符 |
[[:punct:]] | 匹配标点符号 |
[[:space:]] | 匹配空格字符 |
[[:upper:]] | 匹配大写字符 |
[[:word:]] | 匹配单词字符 |
[[:xdigit:]] | 匹配十六进制数字 |