鬼斧神工的正则表达式(PHP语言)

写在前面

正则表达式对于程序员应该算是一个必备的技能了,所以我以PHP语言为载体进行了对正则表达式的学习,也借此继续学习PHP语言,如果需要可以本文中的PHP语言翻译成其他所需的语言。
同时推荐学习正则表达式之前先了解一些基本的语法,基本的OOP思想,基本的MVC模式知识。

与正则表达式的初次邂逅

对于正则表达式,可以在我们使用的很多产品中都有,比如在手机输入法/WINDOWS的文件搜索/WEB界面上对邮箱等的匹配从而判断邮箱是否正确,可以说正则表达式是无孔不入的,借用慕课网中badguy老师对正则表达式的评价:外表风骚,内功深厚!

学习准备

正则表达式的函数解析

PHP中内置的正则表达式的常用函数,函数参数只是列出了必要的参数,对于函数详细用法小伙伴们可以自行查询PHP手册或者自行Google或者百度~
同时建议下面列出的函数可以两两分组进行比较学习。

1
2
preg_match($pattern, $subject)
preg_match_all($pattern, $subject, $matches)

1.preg_match($pattern,$subject,$matches)只将第一个匹配到的结果赋值给$matches,$matches为一维数组。preg_match返回值为匹配到的次数,0或1.

2.preg_match_all($pattern,$subject,$matches)将所有匹配到的结果赋值给$matches,$matches为二维数组。

preg_match_all返回值为匹配到的次数。

1
2
preg_replace($pattern, $replacement, $subject)
preg_filter($pattern, $replacement, $subject)

preg_filter()和preg_replace()区别:在对数组方面替换的时候,preg_replace()会返回所有结果,preg_filter()只会返回替换到的结果。

1
preg_grep($pattern, array $input)

只匹配,不替换,返回匹配到的数组值

1
preg_split($pattern, $subject)

区别explode(…)

1
preg_quote($str)

比较简单,它会将正则表达式中的特殊字符进行转义。
regex的运算符: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
转义符号 \

函数参数说明

为了大家阅读方便,也建议大家在使用过程中使用~

1
2
$pattern = 正则表达式
$subject = 匹配的目标数据

即为在文章或者示例代码中,$pattern 定义的为正则表达式,而 $subjiect 定义的为匹配的目标数据

正则表达式基本语法

正则表达式基本语法归类:

  • 界定符
  • 原子
  • 量词
  • 边界控制
  • 模式单元

虽然第一次学习感觉这些名词都很陌生,但是我相信小伙伴都可以学的明白,因为像我这么善良纯洁的新鲜小码农都了解了,你肯定没有问题啦~

界定符

界定符 :表示一个正则表达式的开始和结束;EG:/[0-9]/;
$pattern = ‘/[0-9]/‘ 或者 #[0-9]# {[0-9]}(不推荐使用大括号);

regexpal工具

正则表达式书写辅助工具 regexpal 是Google Code上的一个开源项目,可以实时匹配正则表达式,方便调试,使用HTML和JS开发,推荐给大家使用。
在线版截图

原子:

可见原子:Unicode编码表中用键盘输出后肉眼可见的字符

  • 标点 _ ;,?等等
  • 英文字母和数字
  • 汉字/日文等其他语言文字
  • 求和等数理化公式符号
  • 其他可见字符
    特殊原子:\ 因为本身还是转义字符,所以要用\才能匹配到一个\符号
    不可见原子:Unicode编码表中用键盘输出后肉眼不可见的字符
  • 换行符 \n
  • 回车符 \r
  • 制表符 \t
  • 空格
  • 其他不可见符号

原子和不可见原子都能用正则表达式进行原子匹配。

元字符:

[] -> 匹配出现在[]中的任意一个原子
| -> 或运算,匹配|符号左右两边的任意一个
[^ ] ->首先这里^必须和[紧挨着,才表示匹配除了[]里面任意原子的字符
[ ^ ]->如果不挨着,就只表示匹配^这种字符了

原子的集合:

  1. . 匹配除换行符之外的任意字符。等价于[^\n]。
  2. \d 匹配任意一个十进制数字,即[0-9]。
  3. \D 匹配任意一个非十进制数字,即[^0-9]。
  4. \s 匹配一个不可见原子,即[\f\n\r\t\v]。
  5. \S 匹配一个可见原子,即[^\f\n\r\t\v]。
  6. \w 匹配任意一个数字,字母或下划线,即[0-9a-zA-Z_]。
  7. \W 匹配任意一个非数字,字母或是下划线,即[^0-9a-zA-Z_]。

量词:

  1. {n} 表示其前面的原子恰好出现n次。
  2. {n,} 表示其前面的原子最少出现n次。
  3. {n,m} 表示其前面的原子最少出现n次,最多出现m次。
    • 匹配0次,1次,或者多次其之前的原子,即{0,}。
    • 匹配1次,或者多次其之前的原子,即{1,}。
  4. ? 匹配0次,1次,或者1次其之前的原子,即{0,1}。

备注:量词不仅支持原子,同样支持原子的集合,同样支持元字符的写法。例如:\w{4}

边界控制与模式单元:

边界控制:

  1. ^ 匹配字符串开始的位置
  2. $ 匹配字符串结尾的位置
    模式单元
  • ()匹配其中的整体为一个原子
    例如:(H|h)ello则匹配Hello和hello的结果。

修正模式

比较重要的两个修正模式:

贪婪匹配
匹配结果存在歧义时取其长
懒惰匹配
匹配结果存在歧义时取其短

其实就是在当匹配结果出现歧义的时候进行修正,默认的修正模式是贪婪匹配。
懒惰模式的标识为大写的U
例如:

1
2
$pattern = '/hello.+12/';
$subject = 'hello__1231321233123131';

在贪婪模式下匹配的结果为:hello__1231321233123131
而修改为懒惰匹配

1
2
$pattern = '/hello.+12/U';
$subject = 'hello__1231321233123131';

那么结果就会变为:hello__12

常见的修正模式:

  • U 懒惰匹配
  • i 忽略英文字母大小写
  • x 忽略空白(空格,制表符等空白符)
  • s 让元字符’.’匹配包括换行符在内的所有字符
  • e 后面单独写下~

如果想同时使用两种修正模式,写法可以如下:

1
$pattern = '/helLo/Ui';

常见正则表达式练习

  1. 非空:

    1
    2
    2. 浮点数匹配
    ```/\d+\.\d{2}$/

    实现保留两位的浮点数,$符号是上文中的边界控制哦~

  2. 手机号匹配

    ```
    1
    2
    3
    匹配到的为1开头,第二位为3,4,5,7,或8的11位手机号
    4. email地址匹配
    ```/^\w+(\.\w+)*@\w+(\.\w+)+$/ (\w 字母,数字,下划线)
  3. URL匹配
    http是否出现,是http还是https。即

    1
    2
    是否是二级域名? 即:
    ```(\w+\.)+。

    顶级域名。即:

    1
    2
    故:正则表达式:
    ```^(https?://)?(\w+\.)+[a-zA-Z]+$

实战:正则工具类的设计实现

话不多说,直接上代码吧~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<?php
class RegexTool {
//常用的regex表达式数组
private $validata = array(
'require' => '/.+/',
'email' => '/^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/',
'url' => '/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?$/',
'currency' => '/^\d+(\.\d+)?$/',
'number' => '/^\d+$/',
'zip' => '/^\d{6}$/',
'integer' => '/^[-\+]?\d+$/',
'double' => '/^[-\+]?\d+(\.\d+)?$/',
'english' => '/^[A-Za-z]+$/',
'qq' => '/^\d{5,11}$/',
'mobile' => '/^1(3|4|5|7|8)\d{9}$/',
);
//返回数组还是返回真假的boolean变量
private $returnMatechResult = false;
//修正模式
private $fixmode = null;
//匹配结果数组
private $matches = array();
//是否匹配成功
private $isMatch = false;
//类的构造函数
public function __construct($returnMatchResult = false, $fixMode = null) {
$this->returnMatchResult = $returnMatchResult;
$this->fixMode = $fixMode;
}
//核心匹配方法
public function regex($pattern ,$subject){
//array_key_exists判断键值是否存在
if (array_key_exists(strtolower($pattern), $this->validata)) {
$pattern = $this->validata[$pattern].$this->fixmode;
}
$this->returnMatchResult?
preg_match_all($pattern, $subject, $this->matches):$this->isMatch = preg_match($pattern, $subject)===1;
return $this->getRegexResult();
}
//获取返回值类型的方法
private function getRegexResult(){
if ($this->returnMatchResult) {
return $this->matches;
}else{
return $this->isMatch;
}
}
//切换返回值类型
public function togoReturnType($boolean = null){
if (empty($boolean)) {
$this->returnMatchResult = !$this->returnMatchResult;
}else{
$this->returnMatchResult = is_bool($boolean)?$boolean:(bool)$boolean;
}
}
//设定修正模式
public function setFixMode($fixMode) {
$this->fixMode = $fixMode;
}
//一些数据验证方法
//是否为空
public function noEmpty($str){
return $this->regex('require',$str);
}
//验证email
public function isEmail($email){
return $this->regex('email',$email);
}
//....其他的类似,省略了,小伙伴自己可以自定义添加哦~
//用户自定义正则表达式
public function check($pattern, $subject) {
return $this->regex($pattern, $subject);
}
}
?>

这个工具已经自己调试过了,如果有问题可以在下面评论交流哦~,欢迎提出改进方案(●ˇ∀ˇ●)
另外上述正则表达式有小伙伴有更好的改进意见的也欢迎交流~(●ˇ∀ˇ●)

ps:对于正则表达式的学习暂时先告一段落了,如果有时间会结合网上的教程自己撸一个简易的Smarty模板引擎,当然只是简易的,届时会在php的分类板块下更新,欢迎小伙伴阅读~
最后感谢慕课网上的相关教程和网上各位大牛的博客和文章,虽然不能一一贴出链接,但谢谢你们的分享。
加油~

坚持原创技术分享,您的支持将鼓励我继续创作!
0%