写在前面
正则表达式对于程序员应该算是一个必备的技能了,所以我以PHP语言为载体进行了对正则表达式的学习,也借此继续学习PHP语言,如果需要可以本文中的PHP语言翻译成其他所需的语言。
同时推荐学习正则表达式之前先了解一些基本的语法,基本的OOP思想,基本的MVC模式知识。
与正则表达式的初次邂逅
对于正则表达式,可以在我们使用的很多产品中都有,比如在手机输入法/WINDOWS的文件搜索/WEB界面上对邮箱等的匹配从而判断邮箱是否正确,可以说正则表达式是无孔不入的,借用慕课网中badguy老师对正则表达式的评价:外表风骚,内功深厚!
学习准备
正则表达式的函数解析
PHP中内置的正则表达式的常用函数,函数参数只是列出了必要的参数,对于函数详细用法小伙伴们可以自行查询PHP手册或者自行Google或者百度~
同时建议下面列出的函数可以两两分组进行比较学习。
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返回值为匹配到的次数。
preg_replace($pattern, $replacement, $subject)
preg_filter($pattern, $replacement, $subject)
preg_filter()和preg_replace()区别:在对数组方面替换的时候,preg_replace()会返回所有结果,preg_filter()只会返回替换到的结果。
preg_grep($pattern, array $input)
只匹配,不替换,返回匹配到的数组值
preg_split($pattern, $subject)
区别explode(…)
preg_quote($str)
比较简单,它会将正则表达式中的特殊字符进行转义。
regex的运算符: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
转义符号 \
函数参数说明
为了大家阅读方便,也建议大家在使用过程中使用~
$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
- 空格
- 其他不可见符号
原子和不可见原子都能用正则表达式进行原子匹配。
元字符:
[] -> 匹配出现在[]中的任意一个原子
| -> 或运算,匹配|符号左右两边的任意一个
[^ ] ->首先这里^必须和[紧挨着,才表示匹配除了[]里面任意原子的字符
[ ^ ]->如果不挨着,就只表示匹配^这种字符了
原子的集合:
- . 匹配除换行符之外的任意字符。等价于[^\n]。
- \d 匹配任意一个十进制数字,即[0-9]。
- \D 匹配任意一个非十进制数字,即[^0-9]。
- \s 匹配一个不可见原子,即[\f\n\r\t\v]。
- \S 匹配一个可见原子,即[^\f\n\r\t\v]。
- \w 匹配任意一个数字,字母或下划线,即[0-9a-zA-Z_]。
- \W 匹配任意一个非数字,字母或是下划线,即[^0-9a-zA-Z_]。
量词:
- {n} 表示其前面的原子恰好出现n次。
- {n,} 表示其前面的原子最少出现n次。
- {n,m} 表示其前面的原子最少出现n次,最多出现m次。
- 匹配0次,1次,或者多次其之前的原子,即{0,}。
- 匹配1次,或者多次其之前的原子,即{1,}。
- ? 匹配0次,1次,或者1次其之前的原子,即{0,1}。
备注:量词不仅支持原子,同样支持原子的集合,同样支持元字符的写法。例如:\w{4}
边界控制与模式单元:
边界控制:
- ^ 匹配字符串开始的位置
- $ 匹配字符串结尾的位置
模式单元
- ()匹配其中的整体为一个原子
例如:(H|h)ello则匹配Hello和hello的结果。
修正模式
比较重要的两个修正模式:
贪婪匹配
匹配结果存在歧义时取其长
懒惰匹配
匹配结果存在歧义时取其短
其实就是在当匹配结果出现歧义的时候进行修正,默认的修正模式是贪婪匹配。
懒惰模式的标识为大写的U
例如:
$pattern = '/hello.+12/';
$subject = 'hello__1231321233123131';
在贪婪模式下匹配的结果为:hello__1231321233123131
而修改为懒惰匹配
$pattern = '/hello.+12/U';
$subject = 'hello__1231321233123131';
那么结果就会变为:hello__12
常见的修正模式:
- U 懒惰匹配
- i 忽略英文字母大小写
- x 忽略空白(空格,制表符等空白符)
- s 让元字符’.’匹配包括换行符在内的所有字符
- e 后面单独写下~
如果想同时使用两种修正模式,写法可以如下:
$pattern = '/helLo/Ui';
常见正则表达式练习
- 非空:
/.+/ - 浮点数匹配
/\d+.\d{2}$/
实现保留两位的浮点数,$符号是上文中的边界控制哦~ - 手机号匹配
/1[34578]\d{9}/
匹配到的为1开头,第二位为3,4,5,7,或8的11位手机号 - email地址匹配
/^\w+(.\w+)*@\w+(.\w+)+$/ (\w 字母,数字,下划线) - URL匹配
http是否出现,是http还是https。即
^(https?://)?。
是否是二级域名? 即:
(\w+.)+。
顶级域名。即:
[a-zA-Z]+。
故:正则表达式:
^(https?://)?(\w+.)+[a-zA-Z]+$
实战:正则工具类的设计实现
话不多说,直接上代码吧~
<?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的分类板块下更新,欢迎小伙伴阅读~
最后感谢慕课网上的相关教程和网上各位大牛的博客和文章,虽然不能一一贴出链接,但谢谢你们的分享。
加油~