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);

    //'/hello/'   进行匹配的模式
    //"hello world"   匹配的字符串
    //$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); //aaaa  world
preg_split
用正则表达式分割字符串

语法:
    array preg_split ( string $pattern , string $subject [, int $limit = -1 [, int $flags = 0 ]] ) 

$pattern: 用于搜索的模式,字符串形式。

$subject: 输入字符串。

$limit: 可选,如果指定,将限制分隔得到的子串最多只有limit个,返回的最后一个 子串将包含所有剩余部分。limit值为-10null时都代表"不限制", 作为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);   //array()

元字符(特殊字符)

*
* 匹配前面的字符零次或多次  等同于 {0,}  

preg_match("/a*/","bbbbba",$res); //array(1) { [0]=> string(0) "" }
+
+匹配前面的字符一次或多次  等同于 {1,}

preg_match("/a+/",'bbbbbbbbbbaa',$res);// array(1) { [0]=> string(2) "aa" }
?
? 匹配前面的字符零次或一次  等同于 {01} 

preg_match("/a?/","aaaabbbb",$res); //array(1) { [0]=> string(1) "a" }
|
| 匹配两个或多个选择  

preg_match("/(h|a)+/","dfghsssssasfgdsf",$res); //array(2) { [0]=> string(1) "h" [1]=> string(1) "h" }
^
^ 匹配字符串的开始位置

preg_match("/^hello/","hello world",$res);//array(1) { [0]=> string(5) "hello" }
$
$ 匹配字符串结束位置

preg_match("/^hello world$/","hello world",$res);//array(1) { [0]=> string(11) "hello world" }
\b
\b 匹配单词的边界(如空格、横杠,但不包括下划线)  更简单点说 \b匹配特殊字符

preg_match("/hello\b/","hello-world",$res);//array(1) { [0]=> string(5) "hello" }
\B
\B 匹配除单词边界以外的部分 更简单点说 \B匹配除了特殊字符以外的字符

preg_match("/hello\B/","hello_world",$res);//array(1) { [0]=> string(5) "hello" }
[]
[] 匹配方括号中的任一字符

preg_match("/[abcdf]/","aaaa -  bbbb - aaac",$res_test);//array(1) { [0]=> string(1) "a" }
[^]匹配除方括号中的字符外的任何字符    

preg_match("/[^abcdf]/","asd",$res_test);//array(1) { [0]=> string(1) "s" }
字符 描述
{m} m 是一个非负整数。匹配确定的 m 次
{m,} m 是一个非负整数。至少匹配m 次
{m,n} 最少匹配 m次且最多匹配 n次
() 表示一个整体
. 匹配除换行之外的任何一个字符
预定义元字符
由于某些模式会反复用到,所以可以使用以下预定义类;
由于某些模式会反复用到,所以可以使用以下预定义类;
\d  匹配一个数字;等价于[0-9]      
    preg_match("/\d+/","asdasdasdad  3434",$res); //array(1) { [0]=> string(4) "3434" }

\D    匹配除数字以外任何一个字符;等价于[^0-9]  
    preg_match("/\D+/","asdasdasdad  3434",$res);//array(1) { [0]=> string(13) "asdasdasdad " }

\w    匹配一个英文字母、数字或下划线;等价于[0-9a-zA-Z_] 
    preg_match("/\w+/","asdasdasdad  3434",$res); //array(1) { [0]=> string(11) "asdasdasdad" }

\W    匹配除英文字母、数字和下划线以外任何一个字符;等价于[^0-9a-zA-Z_]  
    preg_match("/\W+/","asdasdasdad  3434",$res);//array(1) { [0]=> string(2) " " }

\s    匹配一个空白字符;等价于[\f\n\r\t\v]      
    preg_match("/\s+/","asdasdasdad  3434",$res); //array(1) { [0]=> string(2) " " }

\S    匹配除空白字符以外任何一个字符;等价于[^\f\n\r\t\v]   
    preg_match("/\S+/","asdasdasdad  3434",$res);//array(1) { [0]=> string(11) "asdasdasdad" }

匹配字符的开始和结束

在某些情况下,需要对匹配范围进行限定,以获得更准确的匹配结果;

"^"置于字符串的开始确保模式匹配出现在字符串首端;

"$"置于字符串的结束,确保模式匹配出现字符串尾端。

 如果不加边界限制元字符,将获得更多的匹配结果。

$res = preg_match("/^hello/", "hello world"); //int(1)
var_dump($res); //int(1)
$res = preg_match("/world$/", "hello world"); 
var_dump($res); //int(1)

匹配任意字符

"."匹配除换行符外任何一个字符
$res = preg_match('/./', "something"); 
var_dump($res);//int(1)
通常可以使用".*"组合来匹配除换行符外的任何字符

匹配包含某个范围的字符

"[start-end]"匹配包含某个范围的字符

[a-z] 匹配所有的小写字母
[A-Z] 匹配所有的大写字母
[a-zA-Z]  匹配所有的字母
[0-9] 匹配所有的数字
[0-9\.\-] 匹配所有的数字,句号和减号   

$res = preg_match("^[a-z]+$^", "abc"); 
var_dump($res);

重复匹配

正则表达式中有一些用于重复匹配的元字符:"?""*""+"。他们主要的区别是重复匹配的次数不同。

"?" 匹配前面的字符零次或一次  等同于 {01"*" 匹配前面的字符零次或多次  等同于 {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);// array(1) { [0]=> string(5) "HELLO" }

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);// Array ( [0] => Array ( [0] => adsadsa c ) )

x   模式中的空白忽略不计,除非已经转义                          
      preg_match_all("/^    hello /x","hello",$res);//array(1) { [0]=> array(1) { [0]=> string(5) "hello" } }

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";
    //上面部分判断长度是不是11位
    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
    //6-20位字符,必须以字母开头,只能包含数字、字母、下划线,不区分大小写
    $username = "user11";
    $match = '/^[a-zA-Z_][a-zA-Z0-9-_]{5,19}$/';
    if (!preg_match($match, $username)) {
        echo "用户名格式不正确";
    }else{
        echo "用户名格式正确";
    }

?>
密码验证
<?php
    //6-16位字符,需包括数字与英文字母
    $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过于频繁访问该网站时会弹出验证码的窗口,验证是否是机器人。
上面的小说采集的案例里的网站就有这个验证,当出现采集不了时,那有可能触发到该验证了
powered by GitbookEdit Time: 2023-04-08 10:28:32