环视(lookahead),有些也叫零宽断言,不过总感觉这名字太深奥,我喜欢叫环视。

正如它的别名一样,它的匹配是“零宽度”的,是不会占用字符的,只匹配文本中的特定位置,所以环视表达式中匹配的内容是不会被返回的。类似单词分界符 \b,锚点 ^ 和 $

在第三节中,已经粗略的讲了一下环视,乍看起来很简单,但是真正要弄明白却很难,而且它还有四种环视。

虽然有四种,但是理解其中一种,基本其它几种也都触类旁通了。下面就来一一介绍一下

1、肯定顺序环视:(?=pattern)

首先呢,正则的执行顺序是从左至右的,那么这里的意思就是:匹配后面是 pattern 的内容

pattern 可以是确切的字符,如 a,1...,也可以是表达式,如 \d ,[a-z]...

例子23$s = <<

abc

TEXT;

preg_match_all('#ab(?=[a-z])#',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => ab

)

)

*/

匹配ab后面是小写字母的字符串,比如待匹配串是 ab5 ,就不能匹配。

这里只返回了 ab ,为什么呢?这就体现了上面的重点

只匹配文本中的特定位置,所以环视表达式中匹配的内容是不会被返回的

2、否定顺序环视:(?!pattern)

匹配后面不是 pattern 的内容

例子24$s = <<

ab5

TEXT;

preg_match_all('#ab(?![a-z])#',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => ab

)

)

*/

和例子23相反,匹配 ab 后面不是小写字母的字符串

3、肯定逆序环视:(?<=pattern)

上面两种都是顺序(从左至右)的,逆序环视就是解决匹配前面(从右至左)的问题

匹配前面是 pattern 的内容

例子25$s = <<

ab666

TEXT;

preg_match_all('#(?<=[a-z])666#',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => 666

)

)

*/

匹配 666 前面是小写字母的字符串,若把待匹配字符串改为 aB666 ,就不能匹配(因为 B 是大写)

4、否定逆序环视:(?

匹配前面不是 pattern 的内容

例子26$s = <<

123abc

TEXT;

preg_match_all('#(?

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => abc

)

)

*/

匹配 abc 前面不是小写字母的字符串,若把待匹配字符串改为 12dabc ,就不能匹配(因为 d 是包含着字符集 a-z 中的)

四种环视已经介绍完了,还是很好理解的吧,接下来就看一个更复杂的例子

例子27$s = <<

12abc56

7890234

abc

666

a12

b38

TEXT;

preg_match_all('#(?<=)(.+?)(?=\1>)#s',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => 12abc56

[1] => abc

666

)

[1] => Array

(

[0] => a

[1] => m

)

[2] => Array

(

[0] => 12abc56

[1] => abc

666

)

)

*/

我们分成三段来说

(?<=)

匹配前面是 , , 等这样的字符串,并将匹配到的字母捕获(因为加了小括号),以供后面使用

(.+?)

匹配除了 \n 的所有内容(因为用了 .),但是我用了修饰符 s,所以可以换行匹配,所以可以匹配

abc

666

(?=\1>)

匹配后面是 , , 等这样的字符串,那为什么表达式里面没有看见 a,m,b 这样的字母呢?

这里用了"反向引用",仔细阅读前面几节的同学应该都知道,都有提过。

因为正则是从左至右执行的,在第一段子表达式中我们捕获了字母(([a-z]))

由于是第一个捕获(第一个小括号)的内容,所以反向引用就是 \1,若是第二个捕获的内容,就是用 \2,以此类推

那又有人问了:第一个小括号不是 (?<=pattern) 吗?

这就是我反复强调的【环视表达式中匹配的内容是不会被返回的】

那么这里为什么要用反向引用呢,直接写成和前面的一样((?=[a-z]>))不就行了?

这是为了标签配对,不然会匹配到前面是以 a 开头,后面却是以 m 结尾的内容,获取的内容都跨标签了,比如这样:12abc56

7890234

abc

666

注:在这个例子中第三段子表达式即使换成了 (?=[a-z]>) 也还是可以正常匹配,因为第二段子表达式我加了 ? ,非贪婪匹配,若去掉 ? 就会有这种问题

这个表达式可以匹配单个字母标签内的内容,却不能匹配多个字母的标签内容,如例子中的 div

有些人会说,直接在第一段内容中加个 + 号,匹配多个字母不就行了?

这就是接下来要说的一个重要问题

首先说明,这种方法是不行的,逆序环视只能匹配固定长度的内容,当然顺序是可以不固定长度的,比如如下这个匹配div的例子

例子28$s = <<

12abc56

7890234

abc

666

a12

b38

TEXT;

preg_match_all('#(?<=)(.+?)(?=[a-z]+>)#s',$s,$m);

echo "

";

print_r($m);

echo "

";

/*

Array

(

[0] => Array

(

[0] => a12

b38

)

[1] => Array

(

[0] => div

)

[2] => Array

(

[0] => a12

b38

)

)

*/

(?<=)

这里使用了限定符 {3}(第二节有讲哦),说明只匹配三个字母的标签,这样就是定长的

(?=[a-z]+>)

这里我没有使用反向引用,而是直接匹配多个小写字母 [a-z]+,这是不定长的

perl 和 python 的逆序环视是只能匹配固定长度的内容,而php 的正则套件继承的就是 perl 的正则

但是java 的 regex 包的逆序环视是可以不定长的,但长度却是有限的

因为正则是从左到右顺序执行,若逆序执行还不限制长度,那么之前执行过的文本不是每次都要再匹配?匹配次数几何倍增,不推荐也不科学。

布置作业$s = <<

abcd

666

efg

TEXT;

用 【否定逆序环视和否定顺序环视】 匹配出 666

php 正则表达式 环视,正则表达式教程五 —— 环视(零宽断言)相关推荐

  1. 正则表达式之零宽断言

    介绍: 零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像 \b ^ $ \< \> 这样的锚定作用,用于指定一个位置,这个位置应该满足一定的条件(即断言), ...

  2. php 零宽断言,正则表达式之零宽断言实例详解【基于PHP】

    这篇文章主要介绍了正则表达式之零宽断言,简单介绍了零宽断言的概念.分类及php实现技巧与相关注意事项,需要的朋友可以参考下 本文实例讲述了正则表达式之零宽断言.分享给大家供大家参考,具体如下: 前言 ...

  3. php 零宽断言,正则表达式之零宽断言

    介绍: 零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像 \b ^ $ \< \> 这样的锚定作用,用于指定一个位置,这个位置应该满足一定的条件(即断言), ...

  4. grep零宽断言正则表达式

    一.grep零宽断言: (匹配宽度为零,满足一定的条件/断言) 零宽断言用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像 \b ^ $ \< \> 这样的锚定作用, ...

  5. Python正则表达式之零宽断言(4)

    文章目录 声明 | ^ $ \A \Z \b \B 分组 反向引用 注意 声明 有些元字符它们不匹配任何字符,只是简单地表示成功或失败,因此这些字符也称之为零宽断言.例如 \b 表示当前位置位于一个单 ...

  6. 正则表达式零宽断言详解

    在使用正则表达式时,有时我们需要捕获的内容前后必须是特定内容,但又不捕获这些特定内容的时候,零宽断言就起到作用了. 一.基本概念: 零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存 ...

  7. javascript 正则表达式-零宽断言

    http://buzheng.org/blog/regex-zero-width-assertion/ 正则表达式里面比较高级的应用就属于零宽断言了.那么什么是零宽断言呢?拆分法从字面上分析一下,零宽 ...

  8. php 零宽断言,正则表达式之零宽断言实例详解

    这篇文章主要介绍了正则表达式之零宽断言,简单介绍了零宽断言的概念.分类及php实现技巧与相关注意事项,需要的朋友可以参考下 本文实例讲述了正则表达式之零宽断言.分享给大家供大家参考,具体如下: 前言 ...

  9. 【正则表达式系列】零宽断言

    一:基本概念 零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已. 二:用法 1:(?=exp):零宽度正预测先行断言,它断言自身出现的位 ...

最新文章

  1. Firefox 46解决安全问题,改善性能
  2. Thrift的java和php数据交互
  3. ppt android sdk,《0.AndroidSDK概述.ppt
  4. mysql 时间 本周 本月_mysql查询当天、本周、上周、本月、上月信息
  5. mba学什么书_MBA的完整形式是什么?
  6. 收获,不止SQL优化——抓住SQL的本质--第八章
  7. linux怎么删除代码库,是否有从代码库中删除第三方C和C库的好技巧或工具? (OS X或Linux)...
  8. python 读取中文文件名/中文路径
  9. 俄罗斯 IT 存储空间告急,未来 2 月或将耗尽?
  10. 房价――你欠中国老百姓一次彻底的崩盘!
  11. JAVA程序把大写转换小写_Java程序将字符串转换为小写和大写。
  12. 浅谈javascript面向对象理解
  13. Servlet 的运行原理
  14. 随机森林计算特征重要性_随机森林中计算特征重要性的3种方法
  15. 马哥python培训机构怎么样
  16. 大学计算机课实验,大学计算机课程实验教学平台的设计与实现
  17. 3、Linux文件与目录结构
  18. 最优化理论—单纯形法的C++实现(大M法)
  19. 会话管理_优秀会话管理指南
  20. 2019/9/05 软件项目管理作业(用例图)

热门文章

  1. note edge android 6.0 root,三星Note Edge 6.0 root N9150ZCU1CQH5 root 高级设置
  2. Linux下使用md5sum计算和检验MD5码
  3. 阅读--收集--尝试
  4. 【RL-TCPnet网络教程】第30章 RL-TCPnet之SNTP网络时间获取
  5. 过程计算机系统 pcs,过程控制系统(PCS)
  6. jeesite4 下拉框
  7. Docker--容器挂载
  8. STM32笔记--SDIO(SD卡读取)
  9. [书目20150727]有效沟通-余世维
  10. 交易系统处理性能关键指标