个人PHP学习笔记(七)--正则表达式

目录

  • 基本语法
  • 语句结构
  • 函数
  • 数组
  • 面向对象的程序设计
  • 字符串
  • 正则表达式
  • 常用函数
  • 文件系统
  • 图形图像处理
  • MySQL数据库
  • Cookie&Session
  • 错误和异常

正则表达式


正则表达式语法

  • 是一种描述字符排列模式的一种自定义语法规则。
  • 在PHP中可以使用函数联合正则表达式对字符串进行匹配,查找,分割,替换等操作。
  • 正则表达式由原子(普通字符,例如字母A~Z),元字符(有特殊功能的字符,例如*,+和?等)及模式修正符3部分组成。
  • 一个简单的正则表达式,至少要包含一个原子。
  • 在使用PCRE库函数是,一定要给正则表达式加上定界符。

    定界符和原子

定界符
  • 使用PCRE正则表达式通常把函数放入定界符之间。
  • 定界符不局限于反斜杠“\”。除了字母数字和正斜杠“/”之外的全部字符都可以作为定界符。
原子
  • 原子是正则表达式最基本的单位,而且每个模式至少包含一个原子。
  • 原子是由所有那些未指定为元字符的打印和非打印字符组成。
原子字符描述
\cx匹配由x指明的控制字符。\cM匹配一个Control-M或回车符。x的值必须为A~Z或a~z之一,否则,将c视为一个原义的’C’字符
\f匹配一个换页符
\n匹配一个换行符
\r匹配一个回车符
\t匹配一个制表符
\v匹配一个垂直制表符

元字符

  • 用于构建正则表达式的具有特殊含义的字符。
  • 如果要在正则表达式中包含元字符本身,则必须在其前面加上“\”进行转义。
字符描述
$匹配输入字符串的结尾位置。如果设置了RegExp对象的Multiline属性,则$也匹配‘\n’或‘\r’
()标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用
*匹配前面的子表达式零次或多次
+匹配前面的子表达式一次或多次
.匹配除换行符\n之外的任何单字符
[]匹配方括号中指定的任意一个原子
[^]匹配除方括号内原子以外的任意字符
?匹配前面的子表达式零次或一次,或指明一个非贪婪限定符
\将下一个字符标记为特殊字符,原义字符,向后引用,八进制转义符中的一种
^匹配输入字符的开始位置,除非在方括号中使用表示不接受该字符集合
|指明两项之间的一个选择
\s匹配任何空白字符,包括空格,制表符,换页符等
\S匹配任何非空白字符
\w匹配任意一个数字,字母或下划线
\W匹配除数字,字母或下划线以外的任意字符
\b匹配单词的边界
\B匹配除单词边界以外的部分
{n}表示其前面的原子正好出现n次
{n,}表示其前面的原子至少出现n次
{n,m}表示其前面的原子至少出现n次,之多出现m次
通用字符类型
  • 通用字符类型可以匹配相应类型中的任意一个字符。
  • 使用原子表也可以实现同样的功能。例如“[0-9]”就和“\d”的功能是一样的。
正则表达式表示电子邮箱格式

marshall@gmail.com   
//邮箱格式

<?php
    /^[a-zA-Z0-9_]+@[a-zA-Z0-9_]+(\.[a-zA-Z0-9_]+){1,3}$/    
        //原子表形式

    /^\w+@\w+(\.\w+){1,3}$/
        //通用字符形式
?>
限定符
  • 限定符共有6种:“*”,“+”,“?”,“{n}”,“{n,}”,“{n,m}”。
  • 它们的区别在于匹配次数不同。
  • “*”,“+”,“{n,}”都是贪婪限定符,会尽可能多的匹配字符。
<?php
    /a\s*b/         //匹配在a和b之间没有,有一个或者多个空白的情况
    /a\d+b/         //匹配在a和b之间有一个或者多个数字的情况
    /a\\W?b/        //匹配在a和b之间没有或者有一个特殊字符的情况
    /az{2}b/        //匹配在a和b之间必须有两个z的情况
    /az{2,}b/       //匹配在a和b之间至少有两个z的情况
    /az{2,5}b/      //匹配在a和b之间至少有2~5个z的情况 
?>
边界限制
  • 边界限制用来限制字符串或者单词的边界,以获得更精准的匹配结果。
  • “^”和“$”分别表示字符串的开始和结束。
  • “\b”用于匹配字符串中每个单词的前或后边界。“\B”表示非单词边界。
<?php
    /^this/        //匹配this
    /\bis\b/       //匹配is
    /PHP$/         //匹配PHP

    /\Bis\b/       //匹配没有左边界有右边界的is
    /\bis\b/       //匹配有左右边界的is
?>
原点(.)
  • 原点可以匹配目标中的任意一个字符,包括非打印字符。
  • 在默认情况下,它不匹配换行符。
<?php
    /a.b/      
?>
模式选择符(|)
  • ”|“用来分割多个选择,例如,”PHP|HTML“可以匹配”PHP“,也可以匹配”HTML“。
原子表[ ]
  • 原子表”[]“可以匹配一组彼此平等的原子,且从原子表中仅选择一个原子进行匹配即可。
  • 在原子表中可以使用符号”-“来连接ASCII码顺序排列的原子,能够简化书写
<?php
    /[abcp]hp/       //匹配项  ahp  bhp  chp  php

    /[^abc]hp/       //匹配项  ehp  fhp  3hp

    /0[xX]0-9A-F/    //匹配项  0x3F  0X9A  0x5C   
?>
模式单元
  • 模式单元是使用元字符”()“将多个原子组成大的原子被当做一个原子使用。
  • 模式单元中的表达式将被优先匹配
<?php
    /(very)*good/       //匹配项  good  verygood  veryveryverygood
    //"very"被当做一个整体来匹配,因此可以没有也可以有多个
?> 
向后引用
  • 由于模式单元是多个原子,因此这个模式单元会存储在一个临时缓冲区。
  • 缓冲区的编号从1开始,最大可以到编号99.
  • 可以使用”\x“来访问缓冲区的内容,”x“表示编号。在正则表达式中还需要在前面加一个\。
<?php
    /\d{4}(\w)\d{2}\\1\d{2}/          //\1引用了\w
?>
  • 在模式单元匹配成功后,缓存区中的内容就会更新。缓冲区更新就导致了引用的改变,也就是说在模式单元匹配后引用它的地方都要使用匹配的这个原子。
<?php
    /\d{4}(\w)\d{2}\\1\d{2}/          //\1引用了\w
    //2014*12*12

    /\d{4}(\w)\d{2}\\1\d{2}/
    //2014:12:12         
?>
  • 当然这种更新缓冲区是可以由我们控制的,使用”?:“来阻止模式单元被储存。
<?php
    /(windows)(linux)\\2/            //引用第二个缓冲区的内容

    /(?:windows)(linux)\\1/          //第一个模式单元被阻止储存
?>
模式匹配的优先级
  • 相同优先级从左向右运算,不同优先级按优先级从高到低的顺序运算。
优先级元字符描述
1|转义符
2(),(?:),[]模式单元和原子表
3*,+,?,{n},{n,},{n,m}重复匹配
4^,$,\b,\B边界限制
5|模式选择
模式修正符
  • 模式修正符在正则表达式的定界符之外使用。
  • 模式修正符也是可以组合使用的。
  • 模式修正符对编写简洁的正则表达式有很大的帮助。
模式修正符描述
i不区分大小写的匹配
m将字符串视为多行,不管是哪行都能匹配
s将字符串视为单行,换行符作为普通字符
x将模式中的空白忽略
e配合函数preg_replace()使用,可以把匹配来的字符串当做正则表达式执行
A强制从目标字符串开头开始匹配
D如果使用了$限制字符串,则不允许结尾有换行
S如果设定了此修正符则会进行额外的分析
U只匹配最近的一个字符串,不重复匹配

正则表达式函数

PHP支持两套正则表达式处理函数库。

  • ”preg_“为前缀名的PCRE库提供的函数。
  • ”ereg_“为前缀名的POSIX库提供的函数。
函数名描述
preg_match()进行正则表达式匹配
preg_match_all()进行全局正则表达式匹配
preg_replace()进行正则表达式的搜索和替换
preg_split()用正则表达式分割字符串
preg_grep()返回与模式匹配的数组元素
preg_replace_callback()用回调函数执行正则表达式的搜索和替换

字符串查找与替换

  • 字符串匹配与查找是字符串操作中非常重要的内容之一。对于一些比较复杂的字符串替换操作,可以通过正则表达式的替换函数完成。
preg_match()
  • preg_match()用于执行一个正则表达式的匹配。
  • 返回匹配的次数,0表示没有匹配项,1表示有匹配项。
preg_match($pattern,$subject,&$matches,$flags,$offset)

//函数名+接受搜索模式+接受字符串+可选参数(搜索结果组成的数组+使返回结果附加偏移量+指定开始搜索的字符串位置)

//如果设置了第4个参数$flage,则第3个参数$matchesの返回结果会受到影响
//$flage只可以被设置为“PREG_OFFSET_CAPTURE”

<?php
    $email_a='marshall123@gmail.com';
    $email_b='marshall123$gmail.com';
    $res=preg_match('/^\w+@\w+(\.\w+){1,3}$/',$email_a);
    if($res)
    {
        echo '你的邮箱是合法的';
    }
    else
    {
        echo '你的邮箱是不合法的';
    }

    $res=preg_match('/^\w+@\w+(\.\w+){1,3}$/',$email_b);
    if($res)
    {
        echo '你的邮箱是合法的';
    }
    else
    {
        echo '你的邮箱是不合法的';
    }
?>

使用preg_match()并传入多个参数来匹配网址中的域名

<?php
    preg_match('#^(?:http://)?([^/]+)#i','http://www.google.com/index.html',$matches);
    echo '数组的第一个元素内容是:'.$matches[0].'<br/>';
    echo '数组的第二个元素内容是:'.$matches[1].'<br/>';

    $host=$matches[1];
    preg_match('/[^.]+\.[^.]+$/',$host,$matches);
?>
//返回的数组第一个元素将包含完整模式匹配到的文本,第二个元素将包含第一个捕获子组匹配到的文本

<?php
    $str='This is PHP!';
    preg_match('/(\w+) is/i',$str,$res);
    print_r($res);
?>

<?php
    $str='This is PHP!';
    preg_match('/\bis\b/i',$str,$res,PREG_OFFSET_CAPTURE);     //结果相对原字符串的偏移量
    print_r($res);
?>

<?php
    $str='This is PHP!';
    preg_match('/d/',$str,$res,PREG_OFFSET_CAPTURE,4);   //从第4个字符串开始搜索
    print_r($res);
?>
preg_match_all()
  • preg_match_all()会一直搜索到字符串的结尾,获取所有的匹配项。
preg_match_all($pattern,$subject,&$matches,$flags,$offset)

//函数名+接受搜索模式+接受字符串+可选参数(搜索结果组成的数组+使返回结果附加偏移量+指定开始搜索的字符串位置)

preg_match_all()函数会返回整个正则表达式匹配的次数,$flags可以指定的参数有3个。

  • PREG_PATTERN_ORDER:结果排序为$matches[0]保存完整模式的所有匹配,$matches[1]保存第一个子组的所有匹配,以此类推。
  • PREG_SET_\ORDER:结果排序为$matches[0]包含第一次匹配得到的所有匹配(包含子组),$matches[1]是包含第二次匹配到的所有匹配(包含子组)的数组。
  • PREG_OFFSET_CAPTURE:如果这个标记被传递,每个发现的匹配返回时都会增加它相对目标字符串的偏移量。
<?php
    $pat='|<[^>]+>(.*)</[^>]+>|U';
    $str='<b>example:</b><div align=left>This is a test.</div>';
    preg_match_all($pat,$str,$out,PREG_PATTERN_ORDER);
    print_r($out);
?>

//$flags参数对数组内容的影响
<?php
    $pat='|<[^>]+>(.*)</[^>]+>|U';
    $str='<b>example:</b><div align=left>This is a test.</div>';
    preg_match_all($pat,$str,$out,PREG_SET_ORDER);
    print_r($out);
?>

<?php
    $pat='|<[^>]+>(.*)</[^>]+>|U';
    $str='<b>example:</b><div align=left>This is a test.</div>';
    preg_match_all($pat,$str,$out,PREG_OFFSET_CAPTURE);
    print_r($out);
?>
preg_grep()
  • 用于将数组中的元素与正则表达式匹配,返回所有匹配项组成一个数组。
preg_grep($pattern,$input,$flags)     
//函数名+正则表达式+进行匹配的数组+可选参数(可设置为PREG_GREP_INVERT)

<?php
    $arr=array(1,3,67,'s','56','hello','数组','PHP');
    $res=preg_grep('/[0-9]+/',$arr);
    print_r($res);     //返回匹配元素组成的数组
    echo '<br/>';

    $res=preg_grep('/[0-9]+/',$arr,PREG_GREP_INVERT);
    print_r($res);     //返回不匹配元素组成的数组
?>
字符串处理函数strstr(),strpos(),strrpos()和substr()

1.strstr():返回字符串从指定字符串第一次出现的位置开始到结尾的字符串

strstr($haystack,$needle,$before_needle)
//函数名+字符串+指定字符串+可选参数(默认为TRUE,返回从指定字符串第一次出现开始位置的字符串)

<?php
    $str='This is PHP!';
    echo strstr($str,'is');
    echo '<br/><br/>';

    echo strstr($str,'is',TRUE);
    echo '<br/><br/>';

    var_dump(strstr($str,'to'));
?>

//如果想要指定不区分大小写的字符,就需要使用stristr()

2.strpos():返回指定字符在字符串中首次出现的位置。如果指定的值为一个整型数则会被当做字符的ASCII码来匹配字符串

strpos($haystack,$needle,$offset)
//函数名+字符串+指定字符串+可选参数(指定开始搜索的位置,默认值为0)

<?php
    $str='This is PHP!';
    echo strpos($str,'is');
    echo '<br/><br/>';

    echo strpos($str,'is',3);
    echo '<br/><br/>';

    var_dump(strpos($str,'to'));
?>
//在指定开始搜索的位置后,返回的值依然是以字符串开始为基准的
//如果想要指定不区分大小写的字符,就需要使用stripos()
//strrpos()函数用于反悔指定字符串在字符串中最后一次出现的位置

3.substr():用于返回字符串的子串,也就是返回从字符串中指定的字段

substr($string,$start,$length)
//函数名+字符串+指定开始位置+指定长度

在substr()语法中:

  • 如果$start是非负数,返回的字符串将从$string的$start位置开始,从0开始计算。
  • 如果$strat是负数,返回的字符串将从 string start个字符开始。
  • 如果$string的长度小于或等于$start,将返回FALSE。
  • 如果提供了正数的$length,返回的字符串将从$start处开始最多包括$length个字符。
  • 如果提供了负数的$length,那么$string末尾的许多字符将会被漏掉。
  • 如果提供了0,FALSE或NULL的$length,那么将返回一个空字符串。
  • 如果没有提供$length,返回的子字符串将从$start位置开始直到字符串结尾。
<?php
    $res=substr('abcdef',0,-1);
    echo $res.'<br/><br/>';

    $res=substr('abcdef',2,-1);
    echo $res.'<br/><br/>';

    $res=substr('abcdef',4,-4);
    echo $res.'<br/><br/>';

    $res=substr('abcdef',0,-4);
    echo $res.'<br/><br/>';

    $res=substr('abcdef',-3,-1);
    echo $res.'<br/>';
?>

替换字符串

  • 对于一些比较复杂的字符串替换操作,可以通过正则表达式的替换函数preg_replace()来完成。
  • 对字符串做简单的替换处理,从效率方面考虑,建议使用str_replace()。
str_replace()
  • 用于替换字符串,它可以返回一个字符串或者数组。
str_replace($search,$replace,$subject,&$count)
//函数名+查找的目标(可以为数组)+替换值+执行替换的字符串或数组+可选参数(对替换次数进行计数)

<?php
    $str='Hello World!';
    $sea='World';
    $rep='PHP';

    $new_str=str_replace($sea,$rep,$str);

    echo 'Before:'.$str;
    echo '<br/><br/>';
    echo 'After:'.$new_str;
?>

<?php
    $str='Hello World!World!World!';          //重复替换
    $sea='World';
    $rep='PHP';

    $new_str=str_replace($sea,$rep,$str);

    echo 'Before:'.$str;
    echo '<br/><br/>';
    echo 'After:'.$new_str;
?>

//使用数组参数
<?php
    $str='Hello World!';
    $sea=array('Hello','World');
    $rep=('Hi','PHP');

    $new_str=str_replace($sea,$rep,$str);

    echo 'Before:'.$str;
    echo '<br/><br/>';
    echo 'After:'.$new_str;
?>

//实际应用:将编程中常用的换行替换为浏览器中的换行
<?php
    $str='Line1\nLine2\nLine3\n';
    $sea=array('\r\n','\n','\r');
    $rep='<br/>';

    $new_str=str_replace($sea,$rep,$str);

    echo 'Before:'.$str;
    echo '<br/><br/>';
    echo 'After:'.$new_str;
?>

//接受替换的字符串是数组时会出现的情况
<?php
    $str=array('bule','red','yellow','green');
    $new_str=str_replace('red','pink',$str);
    echo 'Before:'.'<br/>';
    print_r($str);
    echo '<br/><br/>';
    echo 'After:'.'<br/>';
    print_r($new_str);
?>

//接受替换的字符和替换字符均为字符串时会出现的特殊情况
<?php
    $str=array('Hello','World','!');
    $sea=array('Hello','World');
    $rep=array('Hi');
    print_r(str_replace($sea,$rep,$str));     //从左到右依次替换,一一对应
?>

//多重替换
<?php
    $str='A';
    $sea=array('A','B','C','D','E');
    $REP=array('B','C','D','E','F');
    echo str_replace($sea,$rep,$str);
    //str_replace()的替换要搜索完全部元素后才会停止。而不是替换一次就停止
?>

<?php
    $str='a p';
    $sea=array('a','p');
    $rep=array('apple','pear');
    echo str_replace($sea,$rep,$str);
?>

//&$count的运用
<?php
    $str='google';
    $sea='o';
    $rep='*';
    $new_str=str_replace($sea,$rep,$str,$count);
    echo 'After:'.$new_str;
    echo '<br/>';
    echo 'Count:'.$count;
?>
preg_replace()
  • preg_replace()与str_replace()的功能类似,最大的不同是preg_replace()使用正则表达式来匹配需要替换的字符串
preg_replace($pattern,$replacement,$subject,$limit=-1,$count)
//函数名+搜索模式+替换项+被替换字符串+可选参数(指定模式替换次数)+统计替换次数

<?php
    $str='goooogle';
    $sea='/o/';
    $rep='*';

    $new_str1=preg_replace($sea,$rep,$str);
    echo 'After:'.$new_str1;
    echo '<br/><br/>';
    $new_str2=preg_replace($sea,$rep,$str,2);
    echo 'After:'.$new_str2;
?>

//preg_replace()的典型使用示例
<?php
    $pattern=array('/(19|20)(\d{2})-(\d{1,2})/','/^\s*{(\w+)}\s*=/');
    $replace=array('\3/\4/\1\2','$\1=');
    echo preg_replace($pattern,$replace,'{startDate}=2012-10-12');
?>

//替换字符串中多个空格为一个空格
<?php
    $str='This    is     PHP   !';
    $new_str=preg_replace('/\s\s+/',' ',$str);
    echo $new_str;
?>

分割和连接字符串

  • 简单的分割可以使用explode()处理,复杂的分割可以使用正则表达式分割函数preg_split()处理。
  • 字符串的连接除了点(.)之外,还可以使用implode()将字符串连接起来。
explode()
explode($separator,$string,$limit)
  • explode()返回由字符串组成的数组,每个元素都是$string的一个子串,它们被字符串$separator作为边界点分割出来
  • 如果$separator为空字符串(“”),explode()将返回FALSE;如果$separator所包含的值在$string中找不到,那么explode()将返回包含$string单个元素的数组。
<?php
    $str='Hello PHP!';
    print_r(explode('#','$str'));     //使用不存在的分隔符
    var_dump(explode('$str'));        //分隔符为空
?>
  • 如果设置了$limit参数,则返回的数组包含最多$limit个元素,而最后那个元素将包含$string的剩余部分。
  • 如果$limit参数是负数,则返回除了最后的$limit个元素外的所有元素。
<?php
    $str='one two three four';
    print_r(explode(' ',$str,2));
    print_r(explode(' ',$str,-2));
?>

//数组
<?php
    $email='marshall@gmail.com';
    $arr=explode('@',$email);
    echo 'UesrName:'.$arr[0];
    echo '<br/><br/>';
    echo 'ServerName:'.$arr[1];
?>
preg_split()
  • preg_split()通过一个正则表达式分割字符串,执行完毕后返回由被分割的字符串作为元素组成的数组。
preg_split($pattern$subject,$limit,$flags)
//函数名+接受正则表达式+接受被分割的字符串+可选参数(控制分割得到的字符串元素个数+可以被设置为几个指定的值)
  • $limit的值如果为-1,0或NULL时都代表“不限制”。
  • $flags可以被指定为下面几个值或多个值得组合(以位或运算“|”组合).
PREG_SPLIT_NO_EMPTY:preg_split()将返回分隔符后的非空部分

<?php
    $str='string';
    $new_str1=preg_split('//',$str,-1);
    $new_str1=preg_split('//',$str,-1,PREG_SPLIT_NO_EMPTY);

    echo '不控制:';
    print_r($new_str1);
    echo '<br/><br/>';
    echo '控制:';
    print_r($new_str2);
?>

PREG_SPLIT_DELIM_CAPTURE:用于分隔的模式中的括号表达式将被捕获并返回

<?php
    $pattern='/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/';
    $replace='2012-10-12';
    print_r(preg_split($pattern,$replace,-1,PREG_SPLIT_DELIM_CAPTURE));
?>

PREG_SPLIT_OFFSET_CAPTURE:对于每一个出现的匹配返回时将会附加字符串偏移量

<?php
    $str='hypertext language programming';
    $chars=preg_split('//',$str,-1,PREG_SPLIT_OFFSET_CAPTURE);
    print_r($chars);
?>
implode()
  • implode()用于把数组元素组合为一个字符串,它可以接受两个参数
implode($separator,$array)
//函数名+可选参数(用于连接元素的字符)+接受用于转换的数组

<?php
    $arr=array('I','Love','PHP','!');
    echo '直接连接:'.implode($arr);
    echo '<br/><br/>';
    echo '使用-连接:'.implode('-',$arr);
?>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值