正则表达式 - 字符组

2023-05-07 21:02:52 浏览数 (2)

        字符组有时也被称为方括号表达式(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 tnr] 或 [ws]

一、匹配十六进制数

        需求为找出含有十六进制数字的字符串。十六进制数字由 0-9、A-F 十六个字符构成,并且假设有三种表示形式:

  • 以 0x 或 0X 为前缀。
  • 以 $ 为前缀。
  • 以 h 或 H 为后缀。

1. 生成测试数据

代码语言:javascript复制
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. 编写正则表达式

代码语言:javascript复制
s(?i)(((0x|$)[a-fd] )|([a-fd] h))s

3. 使用regexp函数查询验证

代码语言:javascript复制
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 会将 ^、$ 等符号作为分隔符的一部分,产生错误的结果:
代码语言:javascript复制
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. 匹配并集

代码语言:javascript复制
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 @rG
*************************** 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. 匹配差集

代码语言:javascript复制
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 @rG
*************************** 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. 匹配字母及数字

代码语言:javascript复制
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 @rG
*************************** 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. 匹配字母

代码语言:javascript复制
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 @rG
*************************** 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. 匹配非字母字符

代码语言:javascript复制
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 @rG
*************************** 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. 匹配空格

代码语言:javascript复制
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. 匹配空白字符

代码语言:javascript复制
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范围内的字符

代码语言:javascript复制
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:]]

匹配十六进制数字

0 人点赞