一、什么时候需要正则表达式
- 数据验证
- 字符串查找
- 字符串替换
二、什么是正则表达式
正则表达式(Regular Expression)是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")。 用它可以匹配、替换、截取匹配的字符串,在处理复杂字符操作的时候,可以提高工作效率,也在一定程度节省你的代码量。
PHP中的正则函数
-
由PCRE库提供的函数,以
preg_
为前缀命名。现在得编程语言和软件中一般都使用PCRE库$str = "PHP编程"; if (preg_match("/([0-9a-zA-Z\x{4e00}-\x{9fa5}]+)/u",$str, $matches)) { var_dump($matches); echo "\n"; }
- 由POSIX扩展的函数,以
ereg_
为前缀命名。自PHP5.3后就不再推荐使用POSIX正则函数库,若程序中使用会报:Deprecated级别的错误
三、正则表达式组成
由定界符、原子、元字符和模式修饰符(也有叫修正符)组成
1、定界符
除了字母、数字、正斜线、\
以外的字符都可以作为定界符号。一般用/
或#
;
$subject="jack is my name,so I'am jack";
$pattern='/jack/';
$pattern='#jack#';
$pattern='/jac/';
echo preg_match($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
$regex = '/^http:\/\/([\w.]+)\/([\w]+)\/([\w]+)\.html$/i';
$str = 'http://www.youku.com/show_page/id_ABCDEFG.html';
$matches = array();
if(preg_match($regex, $str, $matches)){
var_dump($matches);
}
echo '<hr/>';
$regex = '#^http://([\w.]+)/([\w]+)/([\w]+)\.html$#i';
$str = 'http://www.youku.com/show_page/id_ABCDEFG.html';
$matches = array();
if(preg_match($regex, $str, $matches)){
var_dump($matches);
}
2、原子
原子是匹配模式中最基础的组成部分,每个模式至少包含一个原子
2.1、普通原子
1、可见原子 a-z、A-Z、0-9 ( -
连字符表示范围 )
$subject="jack001 is my name,so I'am jack007";
$pattern='/jack[0-9]+/';
$pattern='#jack[0-9]+#';
$pattern='/jac/';
echo preg_match($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
2、不可见原子 \n,\r,\t,\v,\f
字符 | 含义 |
---|---|
\f | 匹配一个换页符。 |
\n | 匹配一个换行符。 |
\r | 匹配一个回车符。 |
\v | 匹配一个垂直制表符 |
\t | 匹配一个水平制表符 |
$subject="jack001
is my name,
so I'am
jack007";
$pattern='/\n/';
echo preg_match_all($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
//\s
jack001
is my name,so I'am jack007 //放到文件里查找
2.2、通用字符
标示 | 说明 |
---|---|
\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_] |
$subject="jack001 is my name,so I'am jack007";
$pattern='/\d/';
$pattern='/\D/';
$pattern='/\w/';
$pattern='/\W/';
echo preg_match_all($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
//实例二
$pattern = '/^[0-9a-zA-Z_]+@[0-9a-zA-Z_]+(\.[0-9a-zA-Z_]+){0,3}$/';
//vs
$pattern = '/^\w+@\w+(\.\w+){0,3}$/';
//实例三
$keywords = preg_split("/[\s,]+/", "hypertext language, programming");
print_r($keywords);
2.3、特殊字符
*`$ ( ) { [ \ . ] } ^ + ?`** 转义后使用
$subject="this is {\$var}";
$pattern='/[\{\}\$]/';
echo preg_match_all($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
2.4、自定义的
[abc] 表示: 匹配a 或者b 或者c
$pattern = '/[abcdef]/';
$subject = 'mystring';
$subject = 'hello boy';
echo preg_match_all($pattern, $subject,$matches);
3、元字符
编写一个正则表达式,我们要用到一些特殊的字符,而这些特殊的字符我们称之为元字符
3.1、限定
常用的限定符
符号 | 说明 |
---|---|
* | 匹配0次、一次或多次其前面的原子 |
+ | 匹配1次或多次其前面的原子 |
? | 匹配0次或1次其前面的原子 |
. | 匹配处理换行符外的任意一个字符 |
| | 匹配两个或多个分支选择 |
{n} | 匹配其前面的原子恰好出现n次 |
{n,} | 表示其前面的原子出现不少于n次 |
{n,m} | 表示其前面的原子至少出现n次,最多出现m次 |
#a\s*b# \s表示空白原子,可以匹配在a和b之间没有空白,一个或多个空白情况
#a\d+b# 可以匹配在a和b之间有一个或多个数字的情况,如a2b,a34567b等
#a\W?b# 可以匹配在a和b之间有一个胡没有特殊字符。如ab,a#b,a%b等
#ax{4}b# 可以匹配在a和b之间必须有4个x的字符串,如axxxb
#ax{2,}b# 可以匹配在a和b之间要至少有2个x的字符,如axxb,axxxxxb等
#ax{2,4}b# 可以匹配在a和b之间至少有2个和最多有4个x的字符串,如果axxb,axxxb,和axxxb
- 点(.)不匹配的换行符在win系统下是[^\n\r],UNIX系统中[^\n]
- (.*?)贪婪模式和修饰符U一样的效果
3.2、定位
符号 | 说明 |
---|---|
^或\A | 匹配输入字符串的开始位置(或在多行模式下行的开头,即紧随一换 行符之后) |
$或\Z | 匹配输入字符串的结束位置(或在多行模式下行的结尾,即紧随一换行符之前) |
\b | 匹配单词的边界 |
\B | 匹配除单词边界以外的部分 |
^jack 以"jack"开头的字符串
jack$ 以"jack"结尾的字符串
^jack$ "jack"开头和结尾,(只能是聂哥自己 )
$subject='he and hello word and here';
$pattern='/he/';//想匹配单词he
$pattern='/\bhe\b/';//想匹配单词he
// $subject='this hello';
// $pattern='#\Bis#';//左边一定无边界
// $subject='singising ';
// $pattern='#is\B#';//不以is结尾 右边一定无边界
// $pattern='#\Bis\B#';//不以is开始也不以is结尾
在字符串"This island is a beautiful land"中
元字符`\b`对单词的边界进行匹配;
/\bis\b/ 匹配单词"is",不匹配"This"和"island"。
/\bis 匹配单词"is"和"island"中的"is",不匹配"This"
元字符“\B”对除单词边界以外的部分进行匹配。
/\Bis\B/ 将明确的指示不与单词的左、右边界匹配,只匹配单词的内部。所以在这个例子中没有结果。
/\Bis 匹配单词"This"中的"is"
echo preg_match_all($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
3.3、范围指定
符号 | 说明 |
---|---|
[ ] | 匹配方括号中指定的任意一个原子 |
[^] | 匹配除方括号中的原子以外的任意一个字符 |
( ) | 匹配其整体为一个原子,即模式单元。可以理解为由多个单个原子组成的大原子 |
[a-z] a到z之间任意字母
[^A-Z] 除了 A-Z这些之外的字符
(gif|jpeg) "gif"或者 "jpeg"
[a-z]+ 一个或者多个 a到z之间任意字母
[0-9.-] 0-9之间任意数字,或者 点 或者 横线
[a-zA-Z0-9_]{1,}$ 至少一个字母数字下划线
([wx])([yz]) wy或wz或xy或xz
[^A-Za-z0-9] 字符数字之外的字符
([A-Z]{3}|[0-9]{4}) 三个大写字母或者4个数字
小括号的作用有两个,一个是改变限定符的作用范围,例如(thirt|four)th表示匹配thirth,fourth,另外一个作用是分组,也就是子表达式,例如(.[0-9]{1,3}){3}是对分组进行操作
3.4 转义
如果想查找或匹配元字符本身,比如*
,?
等就出现问题:没办法指定,因为它们会被解释成别的意思。这时就使用 \
来取消这些字符的特殊意义
4、模式修饰符
用于开启或者关闭某种功能或模式
/正则表达式/模式修饰符
使用几个模式修饰符,它能使你的工作更容易,比如字母大小写敏感性、搜索多个行等等。
修饰符 | 说明 |
---|---|
i | 在正则匹配时不区分大小写 |
m | 将字符串视为多行,当设定了此修正符,行起始(^)和行结束(\$)除了匹配整个字符串开头和结束外,还分别匹配其中的换行符(\n)的之后和之前 |
s | 如果设定了此修正符,则模式中的圆点元字符. 匹配所有的字符,包括换行符。即将字符串视为单行,换行符作为普通字符看待 |
x | 忽略空白,除非进行转义的不被忽略。 |
U | 匹配到最近的字符串, 禁止贪婪匹配,只跟踪到最近的一个匹配符并结束 |
D | 如果设定了此修正符,模式中的行结束($)仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,也会被匹配在里面,如果设定了 m 修正符则忽略此选项 |
//i修饰
$subject = "jack is my name,so I'am JACK";
$pattern = '/jack/i';
$pattern = '/HELLO/';
$subject = 'hello word';
//m修饰
$subject = "jack is my name,\njack is my English name";
$pattern = '/^jack/i';//加上脱字符后只能匹配一个
$pattern = '/^jack/im';//加上修饰符m就匹配第二个jack
//s修饰
//注意此处的单双引号
$subject = "jack001 is my name,\njack is my English name";
$pattern = '/./';
$pattern = '/./s';
//x修饰
$subject = "jack is my name,\njack is my English name"; //注意此处的单双引号
$pattern = '/eng lish/';
$pattern = '/eng lish/ix';//x忽略模式中的空白字符
//U取消贪婪模式
$subject = '<strong>聂哥</strong><strong>帅</strong><strong>不</strong><strong>帅</strong>';
$pattern = '/<strong>.*<\/strong>/';
$pattern = '/<strong>.*<\/strong>/U';
//D修饰
$subject = "so I'm jack\n";
$pattern = '/jack$/';
$pattern = '/jack$/D';//加上D不匹配jack\n
echo preg_match_all($pattern, $subject,$matches);
echo '<pre>';
print_r($matches);
四、正则表达式运算符优先级
正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似
顺序 | 元字符 | 描述 |
---|---|---|
1 | \ | 转义符 |
2 | ()、(?:)、(?=)、 [] | 括号和中括号 |
3 | *,+,?,{n},{n,},{n,m} | 限定符 |
4 | ^,$,\b,\B,\A,\Z | 边界限制 |
5 | | | 替换 |
字符具有高于替换运算符的优先级,使得"m|food"匹配"m"或"food"。若要匹配"mood"或"food",请使用括号创建子表达式,从而产生"(m|f)ood"
$pattern = '/ABC|BCD/';
//我们想是中间的C或者B,但是它只管ABC
$subject = 'ABCCD';
echo preg_match_all($pattern, $subject,$matchs);
echo '<pre>';
print_r($matchs);
断言
http://m.php.cn/article/390651.html demo
正则表达式校验密码
1、密码必须由数字、字符、特殊字符三种中的两种组成;
2、密码长度不能少于8个字符;
满足以上两点,应该怎么实现?
(?!^\\d+$)不能全是数字
(?!^[a-zA-Z]+$)不能全是字母
(?!^[_#@]+$)不能全是符号(这里只列出了部分符号,可自己增加,有的符号可能需要转义)
.{8,}长度不能少于8位
合起来就是
(?!^\\d+$)(?!^[a-zA-Z]+$)(?!^[_#@]+$).{8,}