正则表达式 - 字符组
目录
一、匹配十六进制数
1. 生成测试数据
2. 编写正则表达式
3. 使用regexp函数查询验证
4. 分析与知识点
二、字符组取反
三、并集与差集
1. 匹配并集
2. 匹配差集
四、POSIX字符组
1. 匹配字母及数字
2. 匹配字母
3. 匹配非字母字符
4. 匹配空格
5. 匹配空白字符
6. 匹配ASCII范围内的字符
字符组有时也被称为方括号表达式(bracketed expression)。字符组有助于匹配特定字符或者特定的字符序列。它们可以像字符简写式那样代表一大批字符,比如 \d 匹配的字符与 [0-9] 所匹配的字符一样。但字符组更有针对性,因此用途比简写式更广。下面是一些字符组简单例子。
- 匹配英文元音字母:[aeiou]
- 匹配某个范围的字符:[a-z]、[a-f]
- 匹配一个范围的数字:[0-9]、[3-6]
- 匹配 10~19 的偶数:\b[1][24680]\b
- 匹配 0~99 的偶数:\b[24680]\b|\b[1-9][24680]\b
- 匹配空格和单词字符:[_a-zA-Z0-9 \t\n\r] 或 [\w\s]
一、匹配十六进制数
需求为找出含有十六进制数字的字符串。十六进制数字由 0-9、A-F 十六个字符构成,并且假设有三种表示形式:
- 以 0x 或 0X 为前缀。
- 以 $ 为前缀。
- 以 h 或 H 为后缀。
1. 生成测试数据
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'));
2. 编写正则表达式
\s(?i)(((0x|\$)[a-f\d]+)|([a-f\d]+h))\s
3. 使用regexp函数查询验证
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)
可以看到查询结果包含了所有符合规则的十六进制数。
4. 分析与知识点
- (?i) 修饰符表示后面分组不区分大小写。
- ((0x|\\$)[a-f\\d]+) 分组表示以 0x 或 $ 开始后跟一个或多个十六进制字符。
- ([a-f\\d]+h) 分组表示一个或多个十六进制字符,并以 h 结尾。
- 用选择操作符 | 分别匹配两种情况。
- 正则表达式首尾的 \s 表示只匹配整个十六进制数。注意这里不能使用 \b ,因为 \b 会将 ^、$ 等符号作为分隔符的一部分,产生错误的结果:
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 支持该功能。
1. 匹配并集
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之间的数字。
2. 匹配差集
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字符组
POSIX(Portable Operating System Interface,可移植操作系统接口)是 IEEE 维护的一系列标准,其中包含了一个正则表达式标准(ISO/IEC/IEEE 9945:2009)。该标准提供了一套命名的字符组,其形式为:[[:xxxx:]]。
1. 匹配字母及数字
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 等价。
2. 匹配字母
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)
3. 匹配非字母字符
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)
4. 匹配空格
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)
5. 匹配空白字符
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:]] 不包括回车、换行符。
6. 匹配ASCII范围内的字符
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:]] | 匹配十六进制数字 |