转至:http://iregex.org/blog/negate-match.html
网友cfc4n问及关于(?!)的正则表达式问题。回答之后,顺便总结了一下Perl语言中如何匹配“不出现”某元素,贴在这里。
问题
问题描述
有如下文本,如何使用正则式,将其中不含color选项的item匹配出来?
1 2 3 4 5 6 7 8
|
<item> color:red; </item> <item> size:12; number:45; type:good; </item>
|
典型的错误答案
新手容易提供这样的错误答案:<item>.*?(?!color).*?</item>
。其出发点是正确的:只有当color不出现在目标字串时,该匹配才是所需要的。事实上,这样的正则表达式不能如君所愿,它匹配所有的<item>...</item>
。这是为什么呢?
Perl之排除型匹配
最简单的排除型匹配
匹配是=~
, 不匹配当然是 !~
了。写到这里想到,在正则式中,凡是由=
组成的正则式符号,全可以使用!
来替代,以表现相反的意思。例如(?=)
与(?!)
,(?<=)
与(?<!)
,=~
与!~
。
返回正题,看个例子。如果要检测某字串是否含有good,当然要用if ($string =~/good/)
,如果$string
里有good则条件为真,否则为假;
如果要检测某字串是否不含有good,可以用if ($string !~ /good/)
,如果$string
里没有good则条件为真,否则为假。
这种匹配测试,较适合于在大段的字串中搜索某个简单的模式,然后对于匹配的结果作出两种不同的判断,非此即彼。虽然迅速干练,但是对于复杂情况的判断,还是有些累赘。
对于文章开始提出的问题而言,当然可以这样解决:先搜索所有的 <item>...</item>
,然后分别判断是否存在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=<<END; <item> color:red; </item> <item> size:12; number:45; type:good; </item> END
my @result = $text=~ m!<item>.*?</item>!sg; foreach $item (@result) { if ($item !~ /color/) { print "$item"; } }
|
输出结果是:
1 2 3 4 5
|
<item> size:12; number:45; type:good; </item>
|
虽然也不错,但是它总是“宁可错杀不可错放”地找完所有可能项,再一一重新进行排除。能否一开始就先界定,我们要找的是不含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表示不分大小写;这是域名的特征之一。
回到本题
按照要求,一步步建立这条正则式。
- 该正则式匹配的是
<item>...</item>
结构。因此,正则式以<item>
开始。
- 在
<item>
和</item>
之间不得出现color,是这条正则式的难点。因为,color
可能位于这个结构之内的任意一点,因此要规定,此内任意一点都不得出现color一词。这样的点为:(?!color).
。这样的点重复1+次,正则式写为((?!color).)+
。注意这里有个小陷阱:不要写为(?!color).+
,否则它只描述了最左侧的一点不得出现color,其余部分则都无所谓。而写为((?!color).)+
则保证每一点都不出现color。
- 正则式此时为
<item>((?!color).)+?</item>
。为了节省资源,括号通常写成非捕获模式(?:...)
;为了保证点号匹配换行符,可以指定s模式或使用[\s\S]
代替点号元字符。此处仍使用点号。正则式修改为<item>(?:(?!color).)+?</item>
。
总体来说,环视相对于基本的元字符还是要抽象一些。不过一旦理解并掌握了它,就会发现它在精确匹配和替换时十分有用。上面的分析,希望有所帮助。如果您有类似的问题,欢迎提出。
分享到:
相关推荐
回溯是指当正则表达式中的某一部分无法匹配时,将其之前匹配的字符部分或全部放弃,并尝试其他可能的匹配方式。 非贪婪匹配,或称为惰性匹配,与贪婪匹配相反,它尽可能少地进行匹配,使用量词后加上?来表示。例如...
您可能感兴趣的文章:PHP 正则表达式效率 贪婪、非贪婪与回溯分析(推荐)正则中的回溯定义与用法分析【JS与java实现】编写高质量的js之正确理解正则表达式回溯深度分析正则(pcre)最大回溯/递归限制小议正则表达式效率...
当前国家经济环境的深刻变革要求我国煤炭资源型城市积极转型,在这样的条件下,提出了必须调整城市发展方向促进城市结构改革的论点。...最后,以大同市为例证明了色彩规划法在煤炭资源型城市规划中的运用。
小议经济型酒店消费者心理及消费方向.doc
小议日本循环型社会的形成和改进中学习.doc
5. **消防设施维护缺失**:许多大中型超市安装了消防设施,如火灾自动报警系统和自动喷水灭火系统,但这些设施在投入使用后往往缺乏定期的维护和保养,导致在关键时刻可能无法正常工作,丧失了应有的保护功能。...
小议外汇期权会计在新规则中应用 本文主要探讨了小议外汇期权会计在新规则中的应用,涉及到外汇期权的概念、分类、确认、计量和披露等方面的知识点。 一、外汇期权的概念 外汇期权是一种金融衍生工具,允许持有人...
小议展开增值型内部审计推进116611目标的部署.doc
小议光造型下的雕塑视象.doc
小议和谐高中思想政治课堂的构建.pdf
【小议知识型员工绩效管理的问题与对策】 在当今信息化社会,知识型员工已经成为企业发展的重要驱动力。他们凭借丰富的知识和创新能力,对企业绩效产生深远影响。然而,如何有效地管理和评估这些员工的绩效,成为了...
《小议职业高中数学教学》这篇文章很可能探讨了以下几个关键知识点: 1. **职业教育的数学教学目标**:职业高中的数学教育旨在使学生掌握基本的数学概念和方法,同时强调实际应用,将理论与实践相结合,以满足专业...
小议转型社会下的社保规则入宪.doc
《小议职业高中数学教学》这篇文档,作为压缩包中的主要资源,可能涵盖了关于职业教育领域数学教学的多个重要方面。职业高中的数学教学是连接基础教育与职业教育的关键环节,它既要满足学生对基本数学知识的需求,又...
小议英语教学中的语言艺术.docx
小议环境侵权中的精神损失.doc
小议多媒体授课中的互动性.doc
小议并购重组中的内幕交易.doc
小议机械设计中的CAD技术.pdf