PHP正则表达式
什么是正则表达式
正则表达式就是一套专门用于处理文本的强大工具,可以对进行文本查找,匹配,替换;
正则表达式常用于验证表单提交的内容,比如验证电话号码,Email地址,身份证号码等是否有效;
php支持两种风格的正则表达式:Perl风格 Posix 风格
Perl风格
PCRE全称为Perl Compatible Regular Expression,意思是Perl兼容正则表达式。
PCRE来源于Perl语言,而Perl是对字符串操作功能最强大的语言之一,PHP的最初版本就是由Perl开发的产品。
在PCRE中,通常将正则表达式 包含在两个反斜线"/"之间;
例:"/apple/"
定界符也不仅仅局限于"/"。除了字母、数字和斜线"\"以外的任何字符都可以作为定界符.
像"
Posix 风格
一般而言,实现相同的功能Perl风格的,效率高些,我们一般使用Perl风格的函数!
而且在PHP7.0版本后该风格已经被弃用了
Perl 兼容正则表达式函数
preg_match
preg_match() 进行正则表达式匹配
语法:
int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
参数 |
描述 |
pattern |
要搜索的模式,字符串类型 |
subject |
输入字符串 |
matches |
如果提供了参数matches,它将被填充为搜索结果 |
flags |
flags可以被设置为以下标记值 |
offset |
通常,搜索从目标字符串的开始位置开始 |
例:
$res;
preg_match("/hello/", "hello world", $res);
print_r($res);
preg_match_all
搜索 subject 中所有匹配 pattern 给定正则表达式的匹配结果并且将它们以 flag 指定顺序输出到 matches 中。
在第一个匹配找到后, 子序列继续从最后一次匹配位置搜索。
语法:
int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]]] )
$pattern: 要搜索的模式,字符串形式。
$subject: 输入字符串。
$matches: 多维数组,作为输出参数输出所有匹配结果, 数组排序通过flags指定。
$flags:可以结合下面标记使用(注意不能同时使用PREG_PATTERN_ORDER和 PREG_SET_ORDER):
PREG_PATTERN_ORDER: 结果排序为$matches[0]保存完整模式的所有匹配, $matches[1] 保存第一个子组的所有匹配,
以此类推。
PREG_SET_ORDER: 结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组),
$matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组,以此类推。
PREG_OFFSET_CAPTURE: 如果这个标记被传递,每个发现的匹配返回时会增加它相对目标字符串的偏移量。
offset: 通常, 查找时从目标字符串的开始位置开始。可选参数offset用于 从目标字符串中指定位置开始搜索(单位是字节)。
例:
$res;
preg_match_all("/h/", "hello hello", $res);
print_r($res);
preg_replace
执行正则表达式的搜索和替换
语法:
mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )
参数 |
描述 |
pattern |
要搜索的模式,字符串类型 |
replacement |
用于替换的字符串或字符串数组 |
subject |
要进行搜索和替换的字符串或字符串数组 |
limit |
flags可以被设置为以下标记值每个模式在每个subject上进行替换的最大次数 |
count |
如果指定,将会被填充为完成的替换次数 |
例:
$res = preg_replace("/hello/","aaaa","hello world");
var_dump($res);
preg_split
用正则表达式分割字符串
语法:
array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] )
$pattern: 用于搜索的模式,字符串形式。
$subject: 输入字符串。
$limit: 可选,如果指定,将限制分隔得到的子串最多只有limit个,返回的最后一个 子串将包含所有剩余部分。limit值为-1,
0或null时都代表"不限制", 作为php的标准,你可以使用null跳过对flags的设置。
$flags: 可选,可以是任何下面标记的组合(以位或运算 | 组合):
PREG_SPLIT_NO_EMPTY: 如果这个标记被设置, preg_split() 将进返回分隔后的非空部分。
PREG_SPLIT_DELIM_CAPTURE: 如果这个标记设置了,用于分隔的模式中的括号表达式将被捕获并返回。
PREG_SPLIT_OFFSET_CAPTURE: 如果这个标记被设置, 对于每一个出现的匹配返回时将会附加字符串偏移量.。
注意:这将会改变返回数组中的每一个元素, 使其每个元素成为一个由第0 个元素为分隔后的子串,
第1个元素为该子串在subject 中的偏移量组成的数组。
例:
$str = 'hypertext hanguage hrogramming';
$chars = preg_split('/ /', $str);
var_dump($chars);
元字符(特殊字符)
*
* 匹配前面的字符零次或多次 等同于 {0,}
preg_match("/a*/","bbbbba",$res);
+
+匹配前面的字符一次或多次 等同于 {1,}
preg_match("/a+/",'bbbbbbbbbbaa',$res);
?
? 匹配前面的字符零次或一次 等同于 {0,1}
preg_match("/a?/","aaaabbbb",$res);
|
| 匹配两个或多个选择
preg_match("/(h|a)+/","dfghsssssasfgdsf",$res);
^
^ 匹配字符串的开始位置
preg_match("/^hello/","hello world",$res);
$
$ 匹配字符串结束位置
preg_match("/^hello world$/","hello world",$res);
\b
\b 匹配单词的边界(如空格、横杠,但不包括下划线) 更简单点说 \b匹配特殊字符
preg_match("/hello\b/","hello-world",$res);
\B
\B 匹配除单词边界以外的部分 更简单点说 \B匹配除了特殊字符以外的字符
preg_match("/hello\B/","hello_world",$res);
[]
[] 匹配方括号中的任一字符
preg_match("/[abcdf]/","aaaa - bbbb - aaac",$res_test);
[^]匹配除方括号中的字符外的任何字符
preg_match("/[^abcdf]/","asd",$res_test);
字符 |
描述 |
{m} |
m 是一个非负整数。匹配确定的 m 次 |
{m,} |
m 是一个非负整数。至少匹配m 次 |
{m,n} |
最少匹配 m次且最多匹配 n次 |
() |
表示一个整体 |
. |
匹配除换行之外的任何一个字符 |
预定义元字符
由于某些模式会反复用到,所以可以使用以下预定义类;
由于某些模式会反复用到,所以可以使用以下预定义类;
\d 匹配一个数字;等价于[0-9]
preg_match("/\d+/","asdasdasdad 3434",$res);
\D 匹配除数字以外任何一个字符;等价于[^0-9]
preg_match("/\D+/","asdasdasdad 3434",$res);
\w 匹配一个英文字母、数字或下划线;等价于[0-9a-zA-Z_]
preg_match("/\w+/","asdasdasdad 3434",$res);
\W 匹配除英文字母、数字和下划线以外任何一个字符;等价于[^0-9a-zA-Z_]
preg_match("/\W+/","asdasdasdad 3434",$res);
\s 匹配一个空白字符;等价于[\f\n\r\t\v]
preg_match("/\s+/","asdasdasdad 3434",$res);
\S 匹配除空白字符以外任何一个字符;等价于[^\f\n\r\t\v]
preg_match("/\S+/","asdasdasdad 3434",$res);
匹配字符的开始和结束
在某些情况下,需要对匹配范围进行限定,以获得更准确的匹配结果;
"^"置于字符串的开始确保模式匹配出现在字符串首端;
"$"置于字符串的结束,确保模式匹配出现字符串尾端。
如果不加边界限制元字符,将获得更多的匹配结果。
$res = preg_match("/^hello/", "hello world");
var_dump($res);
$res = preg_match("/world$/", "hello world");
var_dump($res);
匹配任意字符
用"."匹配除换行符外任何一个字符
$res = preg_match('/./', "something");
var_dump($res);
通常可以使用".*"组合来匹配除换行符外的任何字符
匹配包含某个范围的字符
用"[start-end]"匹配包含某个范围的字符
[a-z] 匹配所有的小写字母
[A-Z] 匹配所有的大写字母
[a-zA-Z] 匹配所有的字母
[0-9] 匹配所有的数字
[0-9\.\-] 匹配所有的数字,句号和减号
$res = preg_match("^[a-z]+$^", "abc");
var_dump($res);
重复匹配
正则表达式中有一些用于重复匹配的元字符:"?"、"*"、"+"。他们主要的区别是重复匹配的次数不同。
"?" 匹配前面的字符零次或一次 等同于 {0,1}
"*" 匹配前面的字符零次或多次 等同于 {0,}
"+" 匹配前面的字符一次或多次 等同于 {1,}
"{m}" 匹配确定的 m 次。 m 是一个非负整数;
"{m,n}" 最少匹配 m 次且最多匹配 n 次。 m 和 n 均为非负整数,其中m <= n;
"{m,}" 至少匹配m 次。 m 是一个非负整数;
匹配两个或多个选择
用圆括号"(word1|word2|…)"定义包含word1、word2、…的任意字符串的规则
$res= preg_match ('/^(this|the)/', 'this island is a beautiful land');
var_dump($res);
模式修正符 : 模式修正符在正则表达式定界符之外使用
i 在和模式进行匹配时不区分大小写
preg_match("/hello/i","HELLO WORLD",$res);
m 将字符串视为多行
$str = 'bcd
abc
cba';
preg_match_all('/^abc/m',$str,$arr);
print_r($arr);
s 模式中的圆点元字符 “ . “将匹配所有的字符,包括换行符
$str = 'adsadsa
c';
preg_match_all('/a.*c/s',$str,$arr);
print_r($arr);
x 模式中的空白忽略不计,除非已经转义
preg_match_all("/^ hello /x","hello",$res);
U 取消贪婪匹配
$pattern = '/<b>.*<\/b>/U';
$string = '<b>welcome</b> <b>to</b> <b>phpfuns</b>';
preg_match($pattern,$string,$res);
常用的正则表达式
手机号验证
<?php
header("Content-Type:text/html;charset=utf-8");
$tel = "13055859966";
if (strlen($tel) == "11") {
$reg = "/^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$/";
if (!preg_match($reg, $tel)) {
echo "手机号不正确";
}else {
echo "手机号正确";
}
} else {
echo "长度必须是11位";
}
?>
邮政验证
<?php
header("Content-Type:text/html;charset=utf-8");
$email = '17171226@qq.com';
if (!preg_match('/\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*/', $email)) {
echo "邮箱不合法";
}else {
echo "邮箱合法";
}
?>
url验证
<?php
$url = 'https://www.baidu.com';
$url = strtolower(trim($url ));
if(empty($url )) {
echo "url格式不正确";
}
$match = '/^(http:\/\/)?(https:\/\/)?([\w\d\-]+\.)+[\w\-]+(\/[\d\w\-.\/?%&=]*)?$/';
if (!preg_match($match, $url)) {
echo "url格式不正确";
}else{
echo "url格式正确";
}
?>
用户名验证
<?php
$username = "user11";
$match = '/^[a-zA-Z_][a-zA-Z0-9-_]{5,19}$/';
if (!preg_match($match, $username)) {
echo "用户名格式不正确";
}else{
echo "用户名格式正确";
}
?>
密码验证
<?php
$pwd = "ddkjs3322";
$match = '/^(?![0-9]+$)(?![a-z]+$)(?![A-Z]+$)(?!([^(0-9a-zA-Z)])+$).{6,16}$/';
if (!preg_match($match, $pwd)) {
echo "密码格式不正确";
}else{
ehco "密码正确";
}
?>
用正则表达式采集网站上的图片
采集图片的网址:http://desk.zol.com.cn/qiche/
用正则表达式采集小说网站的小说
采集小说的网址:http://book.zongheng.com/showchapter/984807.html
注意:有些网站防止恶意的访问,当某IP过于频繁访问该网站时会弹出验证码的窗口,验证是否是机器人。
上面的小说采集的案例里的网站就有这个验证,当出现采集不了时,那有可能触发到该验证了