MYSQL:正则表达式

正则表达式介绍

1、在前面学习的过滤例子中允许用匹配、比较和通配操作符寻找数据。对于基本的的过滤(或者甚至是某些不那么基本的过滤),这样就足够了。但随着过滤条件的复杂性的增加,WHERE子句本身的复杂性也有必要的增加。这就是正则表达式变得有用的地方。正则表达式是用来匹配文本的特殊串(字符集合)。正则表达式用正则表达式语言来建立,与其他语言一样,正则表达式具有你必须学习的特殊语法和指令。
2、正则表达式的作用是匹配文本,将一个模式(正则表达式)与一个文本串进行比较。MYSQL用WHERE子句对正则表达式提供了初步的支持,允许你指定正则表达式过滤SELECT检索出的数据

基本字符匹配

例1:

mysql> SELECT platformName FROM roleinfo WHERE channelName REGEXP "pp" ORDER BY platformName;
+---------------+
| platformName  |
+---------------+
| ainjigame_app |
| cinjigame     |
+---------------+

1、上面例子的意思为:从roleinfo表中检索platformName列,返回channelName(任意位置)值中含有"pp"字段的所有行
2、在上面例子中除关键字LIKE被REGEXP替代外,这条语句看上去非常想LIKE语句。它告诉MYSQL:REGEXP后所跟的东西作为正则表达式处理

例2:

mysql> SELECT platformName,channelName,roleName FROM roleinfo WHERE roleName REGEXP ".100" ORDER BY platformName;
+---------------+---------------+----------+
| platformName  | channelName   | roleName |
+---------------+---------------+----------+
| ainjigame_app | bonjigame_bpp | Sbm_100  |
| xinjigame_app | xinjigame_100 | Sam_100  |
+---------------+---------------+----------+

1、这里使用了正则表达式".100",点"."是正则表达式语言中一个特殊字符。它表示表示匹配任意字符。当然这个特殊的例子也可以使用LIKE和通配符来完成

例2_1:

mysql> SELECT platformName,channelName,roleName FROM roleinfo WHERE roleName LIKE "%100" ORDER BY platformName;
+---------------+---------------+----------+
| platformName  | channelName   | roleName |
+---------------+---------------+----------+
| ainjigame_app | bonjigame_bpp | Sbm_100  |
| xinjigame_app | xinjigame_100 | Sam_100  |
+---------------+---------------+----------+

关于LIKE和REGEXP的区别

例3:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName LIKE "100";
Empty set (0.00 sec)
/*可以看到输出为空,即什么也没输出*/

例3_1:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "100";
+---------------+---------------+
| platformName  | channelName   |
+---------------+---------------+
| xinjigame_app | xinjigame_100 |
+---------------+---------------+
1 row in set (0.00 sec)

原因:Like匹配整个列,而正则表达式在是列值内进行匹配

注:
1、like匹配的是被匹配字段的整个值(未使用通配符和定位符时),或者说这个字段中的所有字符都必须被包含在like的匹配规则中,否则匹配失败不返回(除非使用通配符)而正则表达式REGEXP则是在值内进行匹配,只要被匹配的文本在列值中出现,就算是匹配成功,返回行。

2、关于大小写的区分:MySQL中正则表达式匹配(从版本3.23.4后)不区分大小写 。如果要区分大小写,应该使用BINARY关键字,如where post_name REGEXP BINARY 'Hello .000'


关于OR匹配 

作用:为了搜索两个串之一(或者为这个串,或者为另一个串),使用“ | ”

例4:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "100|pp";
+---------------+---------------+
| platformName  | channelName   |
+---------------+---------------+
| xinjigame_app | xinjigame_100 |
| cinjigame     | binjigamecvpp |
+---------------+---------------+ 

注:
1、语句中使用了正则表达式"100|pp"。"|"为正则表达式的OR操作符,它表示匹配其中之一。
2、使用"|"从功能上来看类似于在SELECT语句中使用OR语句,多个OR条件可并入单个正则表达式
3、可以给出两个以上的OR条件,例如"100|200|300"


匹配单一字符:

匹配任何单一字符,可通过指定一组用中括号"[ ]"括起来的字符来完成

例5:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[123] tonanvil";
+---------------+-----------------+
| platformName  | channelName     |
+---------------+-----------------+
| xinjigame_app | 1 tonanvil      |
| cinjigame     | 3 tonanvil      |
| ainjigame_app | 1000 3 tonanvil |
+---------------+-----------------+

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[123]tonanvil";
Empty set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[123]ton";
Empty set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[a|b|c]pp";
+---------------+---------------+
| platformName  | channelName   |
+---------------+---------------+
| cinjigame     | ainjigame_bpp |
| ainjigame_app | ainjigame_app |
+---------------+---------------+

注:
1、这里使用了正则表达式"[123] tonanvil"和"[abc]pp",他们定义了一组字符。它的意思是匹配1或2或3(a或b或c)
2、正如所见,[ ]是另一种形式的OR语句事实上"[123] tonanvil"是"[1|2|3] tonanvil"的缩写,但是必须使用[ ]来定义OR以确定查找什么,否则输出结果可能会与预期的不一致

例5_1:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "1|2|3 ton";
+---------------+----------------+
| platformName  | channelName    |
+---------------+----------------+
| xinjigame_app | 1 ton anvil    |
| cinjigame     | 3 ton anvil    |
| ainjigame_app | ainjigame_1000 |
+---------------+----------------+

注:
1、在上面例子中,输出结果并不是我们所预期的(两个要求的行被检索出来,但还检索出了另外的行)。之所以会这样是由于MYSQL假定你的意思是"1"或"2"或"3 ton"。所以需要把字符"|"括在一个集合中,否则它将应用于整个串

2、^ 否定一个字符集合,将匹配除指定字符外的任何东西。[^123]将匹配除这些字符外的任何东西

例5_2:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[^123]ton";
+---------------+-------------+
| platformName  | channelName |
+---------------+-------------+
| xinjigame_app | 1 ton anvil |
| cinjigame     | 3 ton anvil |
| ainjigame_app | 4 ton anvil |
+---------------+-------------+
3 rows in set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[123] ton";
+---------------+-------------+
| platformName  | channelName |
+---------------+-------------+
| xinjigame_app | 1 ton anvil |
| cinjigame     | 3 ton anvil |
+---------------+-------------+

 

匹配范围

集合可用来定义要匹配的一个或多个字符:如[0123456789]或[0-9]将匹配数字0到9;范围不一定只是数值,[a-z]匹配任一字母字符

例6:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[1-3] ton";
+---------------+--------------+
| platformName  | channelName  |
+---------------+--------------+
| xinjigame_app | .1 ton anvil |
| cinjigame     | 3 ton anvil  |
+---------------+--------------+

注:
这里使用了正则表达式"[1-3] ton"。[1-3]定义了一个范围(包含边界值),这个表达式的意思为匹配1到3。由于1 ton匹配,所以返回了.1 ton anvil


匹配特殊字符

正则表达式语言由具有特定含义的特殊字符构成,目前接触到的有.、[]、|、-等,还有一些其他字符,如果需要匹配这些特殊字符的话,就需要使用转义符(如匹配包含.字符的值)

例7:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP ".";
+---------------+--------------+
| platformName  | channelName  |
+---------------+--------------+
| xinjigame_app | .1 ton anvil |
| cinjigame     | 3 ton anvil  |
| ainjigame_app | 4 ton anvil  |
+---------------+--------------+

注:
1、从上面例子的输出结果来看,输出结果并不是预期的,"."匹配任意字符,因此每个行都被检索出来
2、为了匹配特殊字符,就必须进行转义操作(\\),必须用"\\"为前导

例7_1:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "\\.";
+---------------+--------------+
| platformName  | channelName  |
+---------------+--------------+
| xinjigame_app | .1 ton anvil |
+---------------+--------------+

注:
1、"\\"也用来引用元字符(具有特殊含义的字符)

\\f   换页
\\n 换行
\\r 回车
\\t   制表
\\v 纵向制表

2、为了匹配反斜杠(\)字符本身,需要使用\\\

匹配字符类

值中存在经常使用的数字、所有字母或所有数字字母字符的匹配,可以使用预定义的字符集,称为字符类

[:alnum:]   任意字母和数字(同 [a-zA-Z0-9])
[:alpha:] 任意字符(同 [a-zA-Z])
[:blank:] 空格和制表(同 [\\t])
[:cntrl:]   ASCII控制字符(ASCII 0到31和127)
[:digit:] 任意数字(同[0-9])
[:graph:] 与["print:] 相同,但不包括空格
[:lower:]   任意小写字线(同 [a-z])
[:print:] 任意可打印字符
[:punct:] 既不在 [:alnum:] 又不在 [:cntrl:] 中的任意字符
[space:] 包括空格在内的任意空白字符(同 [\\f\\n\\t\\r\\v])
[:upper:] 任意大小字母(同 [A-Z])
[:xdigit:] 任意十六进制数字(同 [a-fA-F0-9])


匹配多个实例

目前所使用的正则表达式都试图匹配单次出现。但有时需要对匹配的数目进行更强的控制。


元字符  
 说明
*     0个或多个匹配
+     1个或多个匹配(等于 {1, })
?     0个或1个匹配(等于 {0, 1})
{n}   指定数目的匹配
{n, }   不少于指定数目的匹配
{n ,m} 匹配数目的范围(m不超过255)


例8:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "\\([0-9] sticks?\\)";
+---------------+----------------+
| platformName  | channelName    |
+---------------+----------------+
| xinjigame_app | TNT (1 stick)  |
| ainjigame_app | TNT (5 sticks) |
+---------------+----------------+
2 rows in set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "\\([0-9] sticks?)";
+---------------+----------------+
| platformName  | channelName    |
+---------------+----------------+
| xinjigame_app | TNT (1 stick)  |
| ainjigame_app | TNT (5 sticks) |
+---------------+----------------+

注:
正则表达式"\\([0-9] sticks?\\)"。意思为:\\(匹配),[0-9]匹配任意数字,sticks?匹配stick和sticks(s后的?使s可选,因为?匹配它前面的任何字符的0次或1次出现),\\)匹配。没有?,匹配stick和sticks会非常困难

例9:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[[:digit:]]{4}";
+---------------+-------------+
| platformName  | channelName |
+---------------+-------------+
| xinjigame_app | TNT 1000    |
| ainjigame_app | TNT 3000    |
+---------------+-------------+
2 rows in set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "[0-9][0-9][0-9][0-9]";
+---------------+-------------+
| platformName  | channelName |
+---------------+-------------+
| xinjigame_app | TNT 1000    |
| ainjigame_app | TNT 3000    |
+---------------+-------------+

注:
[:digit:]匹配任意数字,因而它为数字的一个集合,{4}要求它前面的字符(任意数字)出现4次,所以[[:digit:]]{4}匹配连在一起的任意4位数字


定位符

目前所用到的正则表达式都是在文本内任意位置查找匹配的(未只用定位符时),在某些情况下我们就需要用到定位符了

^   文本的开始
$   文本的末尾
[[:<:]]   词的开始
[[:>:]]   词的结尾

例10:

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "^[0-9\\.]";
+---------------+--------------+
| platformName  | channelName  |
+---------------+--------------+
| xinjigame_app | .5 ton anvil |
| cinjigame     | 3 ton anvil  |
| ainjigame_app | 1 ton anvil  |
+---------------+--------------+
3 rows in set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "^[\\.]";
+---------------+--------------+
| platformName  | channelName  |
+---------------+--------------+
| xinjigame_app | .5 ton anvil |
+---------------+--------------+
1 row in set (0.00 sec)

mysql> SELECT platformName,channelName FROM roleinfo WHERE channelName REGEXP "^[0-9]";
+---------------+-------------+
| platformName  | channelName |
+---------------+-------------+
| cinjigame     | 3 ton anvil |
| ainjigame_app | 1 ton anvil |
+---------------+-------------+

注:
1、^匹配串的开始。因此,"^[0-9\\.]"只在.或任意数字为串中第一个字符时才匹配他们。
2、^的双重用途:在集合中(用[ ]定义),用它来否定该集合。否则,用来指串的开始(^符合只有在[]内才是取反的意思)。


例11:
用示例,查找用户表中Email格式错误的用户记录:

ELECT * 
FROM users
WHERE email NOT REGEXP '^[A-Z0-9._%-]+@[A-Z0-9.-]+.[A-Z]{2,4}$'



猜你喜欢

转载自blog.csdn.net/qq_39314932/article/details/86097506