网友cfc4n问及关于(?!)的正则表达式问题。回答之后,顺便总结了一下Perl语言中如何匹配“不出现”某元素,贴在这里。 问题 问题描述 有如下文本,如何使用正则式,将其中 不含color选项的item 匹配出来? 1 2 3 4 5 6 7 8 item color:red; /item item size:1

网友cfc4n问及关于(?!)的正则表达式问题。回答之后,顺便总结了一下Perl语言中如何匹配“不出现”某元素,贴在这里。

问题

问题描述

有如下文本,如何使用正则式,将其中不含color选项的item匹配出来?

1

2

3

4

5

6

7

8

color:red;

size:12;

number:45;

type:good;

典型的错误答案

新手容易提供这样的错误答案:.*?(?!color).*?item>。其出发点是正确的:只有当color不出现在目标字串时,该匹配才是所需要的。事实上,这样的正则表达式不能如君所愿,它匹配所有的...。这是为什么呢?

Perl之排除型匹配

最简单的排除型匹配

匹配是=~, 不匹配当然是

!~ 了。写到这里想到,在正则式中,凡是由=组成的正则式符号,全可以使用!来替代,以表现相反的意思。例如(?=)与(?!),(?<=)与(?),=~与!~。

返回正题,看个例子。如果要检测某字串是否含有good,当然要用if

($string =~

/good/),如果$string里有good则条件为真,否则为假;

如果要检测某字串是否不含有good,可以用if

($string !~

/good/),如果$string里没有good则条件为真,否则为假。

这种匹配测试,较适合于在大段的字串中搜索某个简单的模式,然后对于匹配的结果作出两种不同的判断,非此即彼。虽然迅速干练,但是对于复杂情况的判断,还是有些累赘。

对于文章开始提出的问题而言,当然可以这样解决:先搜索所有的 ...,然后分别判断是否存在color项即可:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

#!/usr/bin/perl -w

my $text=

size:12;

number:45;

type:good;

END

my @result =

$text=~ m!.*?item>!sg;

foreach $item (@result)

{

if ($item

!~ /color/)

{

print "$item";

}

}

输出结果是:

1

2

3

4

5

size:12;

number:45;

type:good;

虽然也不错,但是它总是“宁可错杀不可错放”地找完所有可能项,再一一重新进行排除。能否一开始就先界定,我们要找的是不含color的item呢?排除型匹配正是为此而生。

排除型匹配

不好意思,“排除型匹配”这个词是我生造的。其它的说法或许是“否定断言”,“否定环视”等等。后两者的命名,都是从匹配过程的角度出发;而此处命名,是从结果出发。具体说来,就是使用

(?!...)和(?)作为辅助条件判断,来简化正则表达式,方便快捷地找到符合要求的匹配。

这两个东东的使用方法类似,都是指,当前位置不出现某种模式。不同的是,(?!...)是指当前位置的右边,而(?)自然就是指左边了。

这里隆重推出Anrs同学翻译的教程:

环视一以及环视二。仔细阅读这两文章,彻底明白环视这两个概念,将会提升您的正则表达式功力。后文将建立在您已经理解环视这个概念的基础上。

闲话一句。既然使用“左边”和“右边”既形象又好懂,为什么没见过“左瞻”,“右瞻”,“左向”,“右向”,反而全是些“前瞻后瞻”,“正向逆向”这样的不好理解的说法呢?撕烤者也同有此问。我的理解是,或许是为了照顾阿语等从右向左书写的用户的习惯吧。无论如何,将从

^到

$的方向称之为“向前”总不会错。

描述当前位置(左侧或右侧)的模式,从而辅助判断正则式是否匹配,是环视的作用。它只描述,不消耗字符;只辅助判断,从不单独出现。这与^和$简直如出一辙。

一则例子

例子.现在有许多与fanfou.com类似的网址。如何写一条正则表达式,来匹配域名含fanfou,但是TLS不是.com的模式?

答案:/\bfanfou\.(?!com)[a-z]{2,4}\b/i。分析这条正则表达式:

以\b开始,明确字符边界;

fanfou主域名不可少;

\.匹配一个普通的点号;此处不要使用点号元字符;

(?!com)表示此处(即从fanfou.的右边)不得出现com三个连续字符;

[a-z]{2,4}表示是2至4位的拉丁字母;因为域名的TLS最短是2位(如.au,

.us),最长可为4位(如.info, .asia);

右侧边界同样重要,否则我们之前的{2,4}就白费了;

使用i表示不分大小写;这是域名的特征之一。

回到本题

按照要求,一步步建立这条正则式。

该正则式匹配的是...结构。因此,正则式以开始。

在和之间不得出现color,是这条正则式的难点。因为,color可能位于这个结构之内的任意一点,因此要规定,此内任意一点都不得出现color一词。这样的点为:(?!color).。这样的点重复1+次,正则式写为((?!color).)+。注意这里有个小陷阱:不要写为(?!color).+,否则它只描述了最左侧的一点不得出现color,其余部分则都无所谓。而写为((?!color).)+则保证每一点都不出现color。

正则式此时为((?!color).)+?item>。为了节省资源,括号通常写成非捕获模式(?:...);为了保证点号匹配换行符,可以指定s模式或使用[\s\S]代替点号元字符。此处仍使用点号。正则式修改为(?:(?!color).)+?item>。

总体来说,环视相对于基本的元字符还是要抽象一些。不过一旦理解并掌握了它,就会发现它在精确匹配和替换时十分有用。上面的分析,希望有所帮助。如果您有类似的问题,欢迎提出。

exclude,

lookaround,

negate, perl

原文来自:http://iregex.org/blog/negate-match.html

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

php正则取出后不保留左右,PHP 正则 如何匹配不出现某段字符串的写法!(保留备份)...相关推荐

  1. PHP 正则 如何匹配不出现某段字符串的写法!(保留备份)

    网友cfc4n问及关于(?!)的正则表达式问题.回答之后,顺便总结了一下Perl语言中如何匹配"不出现"某元素,贴在这里. 问题 问题描述 有如下文本,如何使用正则式,将其中不含c ...

  2. .net dll反编译源码后,使用vs的正则替换get_和set_

    get_([a-zA-Z0-9]+)\((.+)*?\) 替换为 $1 = $2; 以上()中的表示要保留的元素,按顺序分别对应于替换后的$1 $2 *?表示非贪婪匹配防止匹配失败 用于最新版vsco ...

  3. 有1000枚硬币,其中有10枚是金币,从中取出n枚硬币,求这n枚硬币中有金币的概率。答案保留6位小数

    1.有1000枚硬币,其中有10枚是金币,从中取出n枚硬币,求这n枚硬币中有金币的概率.答案保留6位小数 我们可以逆向思维,可能性只有两种,要么有金的,要么没金的,那我们可以计算没有金的的概率,用(1 ...

  4. 【Rsyslog】 从json 中通过正则 key 获取 value值,rsyslog正则匹配获取key 的 value值

    示例:{srv: 'server1', time: 20210101} 普通正则匹配 则正则表达式为:/(?<=srv:)[^,]*/ 或 /src_ip:([^,]*)/ 可以获取 srv 的 ...

  5. js replace正则匹配替换多个不同字符串的实现方法

    在实际项目开发中,经常会遇到需要替换字符串的情况,简单的使用replace替换指定的一种字符串相信处理起来基本都没啥问题,但遇到一些比较复杂的替换字符串的场景如:需要替换多个不同的字符串,每次正则匹配 ...

  6. 内核添加dts后,device和device_driver的match匹配的变动:通过compatible属性进行匹配【转】...

    本文转载自:http://blog.csdn.net/ruanjianruanjianruan/article/details/61622053 内核添加dts后,device和device_driv ...

  7. jmeter如何通过后置处理器提取(正则提取器、json提取器)做接口关联?

    一.后置处理器-正则表达式提取器 1.添加正则表达式提取 2.正则表达式提取面板介绍: 引用名称:提取引用名称,下个请求要引用此参数名称,如填写token,下个请求中用${token} 正则表达式:( ...

  8. shell 正则取出中间文本。

    文件名称为 build.gradle 所在行内容为 #appVersionCode : 20220811, 取出shell的脚本为 APP_VERSION_CODE=$(egrep "app ...

  9. php 正则筛选靓号如AABBCC(连对),abcdef(顺子)等QQ靓号保留

    正则 行定位符(^与$) 行定位符是用来描述字符串的边界.""表示行结尾,表示行开始eg:he",表示以he开头的字符串"llo"表示行结尾,^表示行 ...

最新文章

  1. cad考试题库绘图题答案_证券从业资格考试证券市场基本法律法规题库答案
  2. Python中yield简单用法
  3. J.U.C之并发工具类:Exchanger
  4. SpringCloud+Redis
  5. ORA-01033 的解决
  6. 算法与数据结构 第3章 高级排序算法中 归并算法改进
  7. 复制网页文本的几种方法
  8. Word2016任意页开始设置页码
  9. [Qt]setGeometry: Unable to set geometry……问题的解决方案
  10. 解决”企业证书打包的ipa,点击app提示未受信任的企业级开发者“的问题
  11. 可以边下边看的BT资源搜索下载工具:Tribler免费版
  12. HTML爱心代码超好看
  13. 程序设计第二十二题 空心三角形
  14. NPDP产品经理小知识:端到端的流程建设与跨职能团队管理
  15. 湿空气性质计算,随笔与学习记录(1.饱和水蒸气压力计算)
  16. 美光科技面试经验总结(2017-1-6)
  17. Error1819(HY000):Your password does not satisfy the current policy requirements
  18. 上海青少年算法竞赛-6月月赛参考代码
  19. [实用技巧] 永久改键软件SharpKeys, 超级好用
  20. 网络安全学习记录-8

热门文章

  1. c语言程序设计上海交通大学,医学院举行“C语言程序设计”教学座谈会
  2. Windows卡死问题分析
  3. MQTT协议应用实例
  4. 让Android的emulator支持web camera
  5. Spring(二) -- 春风拂面之 核心 AOP
  6. python3.8使用requests_python3.8通过python selenium+(requests+BeautifulSoup)对页面进行彻底爬取...
  7. Django中使用后台网站模板
  8. 怎样看懂电路板?电路板短路检查方法是什么?
  9. SAP 外包和外协业务的区别
  10. Python django天天生鲜商城系统