PHP中的正则表达式实例详解


Posted in PHP onApril 25, 2017

最近使用 PHP 写了一个应用,主要是正则表达式的处理,趁机系统性的学习了相应知识。
这篇文章的写作方式不是讲理论,而是通过具体的例子来了解正则,这样也更有实践性,在此基础上再去看正则表达式的基本概念会更有收获。

禁止分组的捕获

在正则中分组很有用,可以定义子模式,然后可以通过后向引用来引用分组的内容,但是有的时候仅仅想通过分组来进行范围定义,而不想被分组来捕获,通过一个例子就能明白:

$str = "http://www.google.com";
$preg= "/http:\/\/\w+\.\w+.(?:net|com|cn)+/is";
$preg2= "/http:\/\/\w+\.\w+.(net|com|cn)+/is";
preg_match($preg,$str,$arr);
preg_match($preg2,$str,$arr2);

当模式中出现?:表示这个括号的分组不会被引用,运行下例子就能明白。

preg_match() 和 preg_match_all() 的区别

preg_match() 在匹配模式的时候匹配到一次就结束,而 preg_match_all() 则进行全局匹配,通过一个例子就能明白:

$str='hello world china';
$preg="/\w+\s/is";
preg_match($preg,$str,$arr);
print_r($arr);
preg_match_all($preg,$str,$arr);
print_r($arr);

正确理解 $ 和 ^

先说一个正则,为了匹配是否是手机号:

$str = "13521899942a";
$preg="/1[\d]{3,15}/is";
if (preg_match($preg,$str,$arr)) {
  echo "ok";
}

虽然字符串中有一个英文字母,但是这个子模式却匹配了,原因就在于模式匹配到后就结束了,不会再去寻找英文字母,为了解决这问题 $ 和 ^ 就发挥作用了,比如让字符串的开始和结尾必须匹配一定的模式,修改如下:

$str = "13521899942a";
$preg="/1[\d]{3,15}$/is";
if (preg_match($preg,$str,$arr)) {
  echo "ok";
}

$ 和 ^ 的跨行模式

默认的情况下,$ 和 ^ 只会匹配完整段落的开始和结尾,但是通过改变选项,允许匹配文本的每一行的开始和结尾,通过下面的例子就能明白

$str='hello
world';
$preg='/\w+$/ism';//$preg='/(?m)\w+$/is';
preg_match_all($preg,$str,$arr);
print_r($arr);

分组命名

在正则中通过括号分组后,可以使用 \1,\2 这样的数字进行后向引用,但是假如正则中模式太多,在使用的时候就会比较混乱,这时候可以采用分组命名来进行引用,看个例子:

$str ="email:ywdblog@gmail.com;";
preg_match("/email:(?<email>\w+?)/is", $str, $matches);
echo $matches["email"] . "_" . $matches['no'];

懒惰模式

正则在匹配的时候是贪婪的,只要符合模式就会一直匹配下去,下面的例子,匹配到的文本是 <h2>hello</h2><h2>world</h2>

$str = "<h2>hello</h2><h2>world</h2>";
$preg = "/<h2>.*<\/h2>/is";
preg_match($preg,$str,$arr);
print_r($arr);

通过改变一个选项可以修改为懒惰模式,就是一旦匹配到就中止,修改代码如下:

$str = "<h2>hello</h2><h2>world</h2>";
$preg = "/<h2>.*?<\/h2>/is";
preg_match($preg,$str,$arr);
print_r($arr);

进一步理解 preg_match_all()

通过这函数的最后一个参数,能够返回不同形式的数组:

$str= 'jiangsu (nanjing) nantong
guangdong (guangzhou) zhuhai
beijing (tongzhou) haidian';
$preg = '/^\s*+([^(]+?)\s\(([^)]+)\)\s+(.*)$/m';
preg_match_all($preg,$str,$arr,PREG_PATTERN_ORDER);
print_r($arr);
preg_match_all($preg,$str,$arr,PREG_SET_ORDER);
print_r($arr);

强大的正则替换回调

虽然 preg_replace() 函数能完成大多数的替换,但是假如你想更好的控制,可以使用回调,不用多说看例子:

$str = "china hello world";
$preg = '/\b(\w+)(\w)\b/';
function fun($m){
    return $m[1].strtoupper($m[2]);
}
echo preg_replace_callback($preg,"fun",$str);

在这一点上,PHP 比 Python 强大的多,Python 中没有正则回调,不过可以使用闭包的方式解决,可看我以前的文章。

preg_quote()

这个函数类似于 Python 中的 re.compile() 函数,假如在模式中一些元字符仅仅想表达字符的本身含义,可以转义,但是假如在模式中写太多的转义,会显得很混乱,可以使用这个函数来统一转义:

$str = '\\*china*world';
$preg = "\*china";
$preg = preg_quote($preg);
echo $preg;
preg_match( "/{$preg}/is",$str,$arr);
print_r($arr);

向前查找 ?= 的妙用

用英文解释可能比较贴切:

The "?=" combination means "the next text must be like this". This construct doesn't capture the text.
(1)这个例子可以获取 URL 中的协议部分,比如 https,ftp,注意 ?: 后面的部分不在返回的内容中。

$str = "http://www.google.com";
$str = "https://www.google.com";
$preg = '/[a-z]+(?=:)/';
preg_match($preg,$str,$arr);
print_r($arr);

(2)"invisible" 分隔符

也叫 “zero-width” 分隔符,参考下面的例子:

$str = ("chinaWorldHello");
$preg = "/(?=[A-Z])/";
$arr = preg_split($preg,$str);
print_r($arr);

(3)匹配强密码

instead of specifying the order that things should appear, it's saying that it must appear but we're not worried about the order.
The first grouping is (?=.{8,}). This checks if there are at least 8 characters in the string. The next grouping (?=.[0-9]) means "any alphanumeric character can happen zero or more times, then any digit can happen". So this checks if there is at least one number in the string. But since the string isn't captured, that one digit can appear anywhere in the string. The next groupings (?=.[a-z]) and (?=.[A-Z]) are looking for the lower case and upper case letter accordingly anywhere in the string.

$str= "HelloWorld2016";
if (preg_match("/^.*(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/", $str,$arr)){
  print_r($arr);
}

向后查找 ?<=

?<= 表示假如匹配到特定字符,则返回该字符后面的内容。
?= 表示假如匹配到特定字符,则返回该字符前面的内容。

$str = 'chinadhello';
$preg = '/(?<=a)d(?=h)/';  
preg_match($preg, $str, $arr);
print_r($arr);

好了,今天的教程就先到这里,有什么问题大家可以留言,我们来讨论下

PHP 相关文章推荐
我的论坛源代码(五)
Oct 09 PHP
第九节--绑定
Nov 16 PHP
php cookie 登录验证示例代码
Mar 16 PHP
PHP 批量更新网页内容实现代码
Jan 05 PHP
php中url传递中文字符,特殊危险字符的解决方法
Aug 17 PHP
PHP is_subclass_of函数的一个BUG和解决方法
Jun 01 PHP
php中$_POST与php://input的区别实例分析
Jan 07 PHP
php实现粘贴截图并完成上传功能
May 17 PHP
在openSUSE42.1下编译安装PHP7 的方法
Dec 24 PHP
PHP中addslashes()和stripslashes()实现字符串转义和还原用法实例
Jan 07 PHP
PHP 类与构造函数解析
Feb 06 PHP
微信封装的调用微信签名包的类库
Jun 08 PHP
PHP利用二叉堆实现TopK-算法的方法详解
Apr 24 #PHP
关于PHP定时发送服务的解决办法
Apr 23 #PHP
php读取和保存base64编码的图片内容
Apr 22 #PHP
PHP7多线程搭建教程
Apr 21 #PHP
mac系统下安装多个php并自由切换的方法详解
Apr 21 #PHP
php获取excel文件数据
Apr 21 #PHP
PHP实现限制IP访问的方法
Apr 20 #PHP
You might like
咖啡店都有些什么常规豆子呢?有什么风味在里面
2021/03/04 咖啡文化
解析php安全性问题中的:Null 字符问题
2013/06/21 PHP
利用“多说”制作留言板、评论系统
2015/07/14 PHP
php实现给二维数组中所有一维数组添加值的方法
2017/02/04 PHP
ajax调用返回php接口返回json数据的方法(必看篇)
2017/05/05 PHP
用JS实现一个页面多个css样式实现
2008/05/29 Javascript
jQuery建立一个按字母顺序排列的友好页面索引(兼容IE6/7/8)
2013/02/26 Javascript
JS生成不重复随机数组的函数代码
2014/06/10 Javascript
JSONP之我见
2015/03/24 Javascript
浅析JS原型继承与类的继承
2016/04/07 Javascript
jQuery实现选项联动轮播效果【附实例】
2016/04/19 Javascript
Vue.JS入门教程之自定义指令
2016/12/08 Javascript
详解用webpack2.0构建vue2.0超详细精简版
2017/04/05 Javascript
Vue.js 2.0 移动端拍照压缩图片预览及上传实例
2017/04/27 Javascript
详解Vue 方法与事件处理器
2017/06/20 Javascript
react-native-fs实现文件下载、文本存储的示例代码
2017/09/22 Javascript
Vue 中使用vue2-highcharts实现曲线数据展示的方法
2018/03/05 Javascript
回顾Javascript React基础
2019/06/15 Javascript
bootstrap 日期控件 datepicker被弹出框dialog覆盖的解决办法
2019/07/09 Javascript
Vue的data、computed、watch源码浅谈
2020/04/04 Javascript
jQuery实现鼠标滑动切换图片
2020/05/27 jQuery
[49:08]Secret vs VP 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/20 DOTA
详细介绍Ruby中的正则表达式
2015/04/10 Python
简单介绍Python中的JSON使用
2015/04/28 Python
浅谈numpy数组的几种排序方式
2017/12/15 Python
python中文编码与json中文输出问题详解
2018/08/24 Python
详解python的argpare和click模块小结
2019/03/31 Python
python程序 线程队列queue使用方法解析
2019/09/23 Python
解决django后台管理界面添加中文内容乱码问题
2019/11/15 Python
Python解压 rar、zip、tar文件的方法
2019/11/19 Python
Pytorch使用MNIST数据集实现CGAN和生成指定的数字方式
2020/01/10 Python
Python变量及数据类型用法原理汇总
2020/08/06 Python
Bugatchi官方网站:男士服装在线
2019/04/10 全球购物
读书小明星事迹材料
2014/05/03 职场文书
80后婚前协议书范本
2014/10/24 职场文书
毕业生自荐信范文
2015/03/05 职场文书