CSS权重指的是样式表规则(包括内联样式、ID选择器、类选择器、标签选择器、通配符和继承属性)对元素样式影响的优先级。CSS权重越高,其样式优先级也越高,会覆盖掉其他具有低权重的样式。
具体来说,CSS权重的计算方式为:
CSS权重的作用在于解决多个样式规则同时作用于一个元素时的样式冲突问题,为页面提供了更细粒度的控制。通过设置适当的CSS权重,可以确保页面元素的样式在多个样式规则中按照预期方式进行呈现。
了解CSS权重对于编写高质量的CSS样式表非常重要,原因如下:
因此,理解CSS权重计算规则是编写高质量CSS代码的重要一步。
CSS选择器是用于选择和描述HTML或XML文档中的元素的模式。
选择器的基本结构包括:
以上这些选择器可以组合在一起并嵌套,形成更复杂的选择模式。
例如,组合选择器的形式如下:
以上这些选择器的灵活组合可以满足多样化的选择需求。知道如何结合使用和优化选择器对于撰写高效、可维护的 CSS 代码非常重要。
CSS 权重用于定义多个 CSS 规则什么时候应该优先应用。我们可以根据规则计算并比较它们的权重来确定最终的样式规则。
CSS 权重的计算方法如下:
计算过程:
下面举例说明几种不同情况下 CSS 权重的计算方法:
由于 CSS 选择器的组合方式非常灵活,因此需要小心使用,并确保正确计算权重,以免产生样式覆盖等问题。
CSS 中有多种选择器类型,每种类型的权重级别是不同的。下面是各种选择器类型的权重级别:
根据以上规则计算同一元素上不同选择器的权重,可以确定最终的样式,同时也可以避免选择器的冲突和样式的覆盖。
需要注意的是,在实际应用中,多个选择器组合在一起的复合选择器(compound selectors)会影响权重的计算。比如 .class1 .class2,权重是 class 为 10,而不是 20。
CSS 的选择器类型有很多种,常见的选择器类型如下:
这些选择器类型可以根据需求进行组合,形成不同的选择器模式,能够支持更复杂的选择。例如,可以使用 class 选择器和伪类选择器结合,来选择页面中特定的菜单组件,也可以使用后代选择器和属性选择器,来选择页面中特定的表单元素。
ID 选择器(ID selector)是一种 CSS 选择器,用于标识 HTML 元素的唯一标识。它通过匹配 HTML 元素的 id 属性的值来选择元素。在 CSS 规则中,ID 选择器需要以 “#” 符号开头,后面跟着 id 的值。
ID 选择器的使用方法是,为 HTML 元素设置一个 id 属性,并在 CSS 样式表中为该元素的 ID 选择器指定样式。例如,在 HTML 中设置一个带有 id 属性的链接元素:
<a href="#" id="my-link">Click here</a>
然后,在 CSS 样式表中,使用该链接元素的 ID 选择器来设置样式:
#my-link {
color: red;
text-decoration: none;
}
在上例中,ID 选择器 “#my-link” 指定链接元素的颜色为红色,且没有下划线。需要注意的是,ID 选择器唯一标识页面中的某个元素,每个元素只能有一个 ID,而且 ID 选择器的权重很高,比其他选择器都要高,因此应该慎重使用。
鉴于 ID 选择器的高权重和唯一性,它常用于给页面中的某些元素添加特别的样式,如页面顶部的 LOGO、导航、侧边栏、页脚、表单等等。
Class 选择器(class selector)是一种 CSS 选择器,它用于选择拥有相同 class 属性值的 HTML 元素。在 CSS 规则中,Class 选择器以 “.”(英文句号)开头,后面紧跟着类名。
Class 选择器的使用方法是,在 HTML 元素的 class 属性中指定类名,并通过 CSS 样式表中的类名选择器来定义该类元素的样式。例如,在 HTML 中为一个段落元素定义 class 属性:
<p class="intro">这是一段简介</p>
然后,在 CSS 样式表中,使用该段落元素的类名选择器来设置样式:
.intro {
font-size: 18px;
color: #333;
}
在上例中,Class 选择器 “.intro” 指定段落元素的字体大小为 18 像素,颜色为 #333。
Class 选择器可以应用于页面中多个元素,一个元素可以拥有多个类名,而且类名之间可以以空格分隔。例如:
<div class="container header">...</div>
以上是一个拥有两个类名的 div 元素,它将继承所有类名定义的样式。
Class 选择器的使用相对灵活,因此在样式表中广泛使用。它可以帮助开发者快速改变一组元素的样式,也可以用于指定网站中的主色调、边距、定位等属性。
元素选择器是CSS中最基本的选择器类型之一,它通过匹配HTML元素的标签名称来选择样式。它使用单一元素的标签名称,如div、p、h1、span等作为选择器。
一个元素选择器在CSS中的定义方式非常简单,就是使用HTML元素名作为选择器,例如:
p {
color: blue;
}
上面的代码将文本的颜色样式设置为蓝色。它会选择HTML文档中所有的<p>元素,并将他们的颜色样式设置为蓝色,从而改变了文本的颜色。
元素选择器的优点是易于使用和定义。但是,它也有一些缺点,因为它只使用标签名称来匹配元素。它无法限制所匹配的元素具有特定的类或ID属性,也不能选择某个元素在其父级元素内的位置。
总体而言,元素选择器是CSS样式定义中最基本和经典的方式之一,可以作为基准选择器,随着更复杂和精细的选择器的逐渐引入,它的应用也越来越广泛。
通配符(wildcard)是 CSS 选择器中的一种选择方式,使用 * 作为选择器。它可以匹配页面中的所有元素,因此被称为万能选择器。
通配符的使用方法是,在 CSS 样式表中使用 * 符号作为选择器:
* {
box-sizing: border-box;
}
在上面的代码中,使用了通配符来指定页面中所有元素的 box-sizing 属性为 border-box。这种写法的效果相当于在 HTML 页面的所有元素中都声明了 box-sizing 属性。
通配符应该谨慎使用,因为它会递归遍历整个文档,使浏览器处理的时间变长,也不利于性能优化。通配符可能会导致特定的样式被覆盖或无法继承,因此在实际开发中不建议经常使用。
CSS继承是一种CSS样式定义的机制,它允许样式从一个元素传递到其子元素,从而节省CSS代码和减少样式的重复定义。
CSS中的继承是通过使用inherit值来实现的,它指示子元素应该继承父元素的某个CSS属性。例如,以下代码将字体颜色设置为蓝色:
body {
color: blue;
}
在这个示例中,color属性被应用于body元素,我们也可以在子元素继承该颜色:
p {
font-size: 14px;
}
使用继承,我们并没有在p元素中再次定义color属性,但是p元素会继承color属性,因此该元素中的文本颜色也将是蓝色。当然,它也可以通过显式地定义一个新的color属性来覆盖从父元素继承的该属性。
需要注意的是,并不是所有的CSS属性都支持继承,只有一部分属性才可以被继承,如字体样式、文本排布、颜色等基本元素。例如,background属性就不支持继承,所以子元素不会继承其父元素的背景颜色。
继承可以提高CSS代码的可读性和可维护性,同时也可以减少代码的冗余度。不过要注意,过多地使用继承也可能会使得CSS代码变得过于复杂和难以维护,需要在实际应用中进行权衡和使用。
在 CSS 样式表中,如果有两个规则应用于同一个元素,且优先级相同,那么后定义的规则会覆盖先定义的规则。这个原则被称为“后定义的优先”。
例如,如果页面中有如下的规则:
p {
color: red;
}
p {
color: blue;
}
那么应用于页面中的所有段落元素的颜色将是蓝色,因为后一个规则优先级更高,会覆盖前一个规则。
需要注意的是,只有在选择器和属性相同的情况下,才会使用“后定义的优先”规则。如果这两个规则中有任何一个选择器不同,那么不能简单地使用“后定义的优先”规则。
例如,如果页面中有如下规则:
p {
color: red;
}
h1 {
color: blue;
}
其中第一个规则应用于所有段落元素,而第二个规则应用于所有标题元素,这两个选择器不能互相覆盖。因此,“后定义的优先”规则在这种情况下不适用。
总之,“后定义的优先”规则只适用于同时应用于同一元素并且选择器和属性都相同的情况。在编写 CSS 样式表时,我们应该注意避免定义相同的规则,以免性能下降和样式出现不可预期的问题。
CSS 权重是指网页中元素被样式引用的优先级,因此很重要。在 CSS 样式表中,如果存在多个样式规则可以应用于同一元素,那么 CSS 样式将根据其权重决定哪一个规则会被应用。
CSS 权重的重要性主要体现在以下几个方面:
在编写 CSS 样式表时,需要仔细考虑选择器和样式规则的设计和顺序。理解 CSS 权重的规则和操作方法,可以更好地控制样式的显示优先级,并在保证代码质量的同时提高页面性能。
优化CSS代码有助于提高网页的性能和用户体验。以下是几个优化CSS代码的技巧:
总之,优化CSS代码可以提高页面性能和用户体验,需要遵循一些基本原则和技巧来实现。
编写可维护的 CSS 代码是一项非常重要的技能,以下是一些可行的技巧和最佳实践:
1. 使用 BEM 命名规则
BEM 是一种简单易懂的 CSS 命名规范。BEM 命名方式基于块(block)、元素(element)、修饰符(modifier)等三个概念,可以帮助我们更好地管理 CSS codebase。
BEM 的命名方式一般是 block__element--modifier 的格式,例如:
.main-nav {}
.main-nav__item {}
.main-nav__item--active {}
2. 使用变量
CSS 变量可以帮助我们更轻松地重用颜色、字体大小、间距等属性,从而简化整个样式表的实现。可以通过 :root 选择器来定义全局变量,例如:
:root {
--primary-color: #27ae60;
--nav-height: 80px;
}
.nav {
height: var(--nav-height);
background-color: var(--primary-color);
}
3. 避免使用标签选择器
避免使用标签选择器,而是尽可能使用类选择器或 ID 选择器,可以帮助我们更好地封装和重用样式,并且避免样式的混乱和嵌套过多。
4. 布局使用 Flexbox 和 Grid
使用 Flexbox 和 Grid 可以让您更轻松地管理布局,实现响应式和复杂布局。
5. 避免使用全局样式
全局样式会影响整个站点,并且更难以维护。应该尽可能地将样式限制在特定的组件或模块中。
6. 使用预处理器
使用预处理器,例如 Sass 或 LESS,可以帮助我们更好地组织和抽象样式代码,从而让代码更简洁、更易于维护。
7. 设计统一的代码风格
在项目中设定统一的 CSS 编码规范,可以提高代码的可读性和可维护性。
总之,可维护的 CSS 代码是一个循序渐进的过程,在实践中不断总结并寻找本质的解决方案,才能对代码的臃肿和性能瓶颈有所突破。
|
|
2.@”是指令“v-on”的缩写;
|
它们不会出现在最终渲染的标记中。缩写语法是完全可选的
.
@就是是当前项目的路径
|
v- 前缀作为一种视觉提示,用来识别模板中 Vue 特定的特性。
3 . .修饰符
修饰符 (Modifiers) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():
|
文目标
30分钟内让你明白正则表达式是什么,并对它有一些基本的了解,让你可以在自己的程序或网页里使用它
正则表达式到底是什么东西?
字符是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等。字符串是0个或更多个字符的序列。文本也就是文字,字符串。说某个字符串匹配某个正则表达式,通常是指这个字符串里有一部分(或几部分分别)能满足表达式给出的条件。
在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。
很可能你使用过Windows/Dos下用于文件查找的通配符(wildcard),也就是*和?。如果你想查找某个目录下的所有的Word文档的话,你会搜索*.doc。在这里,*会被解释成任意的字符串。和通配符类似,正则表达式也是用来进行文本匹配的工具,只不过比起通配符,它能更精确地描述你的需求——当然,代价就是更复杂——比如你可以编写一个正则表达式,用来查找所有以0开头,后面跟着2-3个数字,然后是一个连字号“-”,最后是7或8位数字的字符串(像010-12345678或0376-7654321)。
入门
学习正则表达式的最好方法是从例子开始,理解例子之后再自己对例子进行修改,实验。下面给出了不少简单的例子,并对它们作了详细的说明。
假设你在一篇英文小说里查找hi,你可以使用正则表达式hi。
这几乎是最简单的正则表达式了,它可以精确匹配这样的字符串:由两个字符组成,前一个字符是h,后一个是i。通常,处理正则表达式的工具会提供一个忽略大小写的选项,如果选中了这个选项,它可以匹配hi,HI,Hi,hI这四种情况中的任意一种。
不幸的是,很多单词里包含hi这两个连续的字符,比如him,history,high等等。用hi来查找的话,这里边的hi也会被找出来。如果要精确地查找hi这个单词的话,我们应该使用\bhi\b。
\b是正则表达式规定的一个特殊代码(好吧,某些人叫它元字符,metacharacter),代表着单词的开头或结尾,也就是单词的分界处。虽然通常英文的单词是由空格,标点符号或者换行来分隔的,但是\b并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置。
如果需要更精确的说法,\b匹配这样的位置:它的前一个字符和后一个字符不全是(一个是,一个不是或不存在)\w。
假如你要找的是hi后面不远处跟着一个Lucy,你应该用\bhi\b.*\bLucy\b。
这里,.是另一个元字符,匹配除了换行符以外的任意字符。*同样是元字符,不过它代表的不是字符,也不是位置,而是数量——它指定*前边的内容可以连续重复使用任意次以使整个表达式得到匹配。因此,.*连在一起就意味着任意数量的不包含换行的字符。现在\bhi\b.*\bLucy\b的意思就很明显了:先是一个单词hi,然后是任意个任意字符(但不能是换行),最后是Lucy这个单词。
换行符就是'\n',ASCII编码为10(十六进制0x0A)的字符。
如果同时使用其它元字符,我们就能构造出功能更强大的正则表达式。比如下面这个例子:
0\d\d-\d\d\d\d\d\d\d\d匹配这样的字符串:以0开头,然后是两个数字,然后是一个连字号“-”,最后是8个数字(也就是中国的电话号码。当然,这个例子只能匹配区号为3位的情形)。
这里的\d是个新的元字符,匹配一位数字(0,或1,或2,或……)。-不是元字符,只匹配它本身——连字符(或者减号,或者中横线,或者随你怎么称呼它)。
为了避免那么多烦人的重复,我们也可以这样写这个表达式:0\d{2}-\d{8}。这里\d后面的{2}({8})的意思是前面\d必须连续重复匹配2次(8次)。
测试正则表达式
如果你不觉得正则表达式很难读写的话,要么你是一个天才,要么,你不是地球人。正则表达式的语法很令人头疼,即使对经常使用它的人来说也是如此。由于难于读写,容易出错,所以找一种工具对正则表达式进行测试是很有必要的。
不同的环境下正则表达式的一些细节是不相同的,本教程介绍的是微软 .Net Framework 4.5 下正则表达式的行为,所以,我向你推荐我编写的.Net下的工具 Regester。请参考该页面的说明来安装和运行该软件。
元字符
现在你已经知道几个很有用的元字符了,如\b,.,*,还有\d.正则表达式里还有更多的元字符,
下面来看看更多的例子:
\ba\w*\b匹配以字母a开头的单词——先是某个单词开始处(\b),然后是字母a,然后是任意数量的字母或数字(\w*),最后是单词结束处(\b)。
\d+匹配1个或更多连续的数字。这里的+是和*类似的元字符,不同的是*匹配重复任意次(可能是0次),而+则匹配重复1次或更多次。
\b\w{6}\b 匹配刚好6个字符的单词。
常用的元字符
.匹配除换行符以外的任意字符
\w匹配字母或数字或下划线或汉字
\s匹配任意的空白符
\d匹配数字
\b匹配单词的开始或结束
^匹配字符串的开始$匹配字符串的结束
元字符^(和数字6在同一个键位上的符号)和$都匹配一个位置,这和\b有点类似。^匹配你要用来查找的字符串的开头,$匹配结尾。这两个代码在验证输入的内容时非常有用,比如一个网站如果要求你填写的QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$。
这里的{5,12}和前面介绍过的{2}是类似的,只不过{2}匹配只能不多不少重复2次,{5,12}则是重复的次数不能少于5次,不能多于12次,否则都不匹配。
因为使用了^和$,所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须是5到12个数字,因此如果输入的QQ号能匹配这个正则表达式的话,那就符合要求了。
和忽略大小写的选项类似,有些正则表达式处理工具还有一个处理多行的选项。如果选中了这个选项,^和$的意义就变成了匹配行的开始处和结束处。
字符转义
如果你想查找元字符本身的话,比如你查找.,或者*,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。这时你就得使用\来取消这些字符的特殊意义。因此,你应该使用\.和\*。当然,要查找\本身,你也得用\.
例如:deerchao\.net匹配deerchao.net,C:\Windows匹配C:\Windows。
重复
你已经看过了前面的*, +, {2}, {5,12}这几个匹配重复的方式了。下面是正则表达式中所有的限定符(指定数量的代码,例如*, {5,12}等):
常用的限定符
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次
下面是一些使用重复的例子:
Windows\d+匹配Windows后面跟1个或更多数字
^\w+匹配一行的第一个单词(或整个字符串的第一个单词,具体匹配哪个意思得看选项设置)
字符类
要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),应该怎么办?
很简单,你只需要在方括号里列出它们就行了,像[aeiou]就匹配任何一个英文元音字母,[.?!]匹配标点符号(.或?或!)。
我们也可以轻松地指定一个字符范围,像[0-9]代表的含意与\d就是完全一致的:一位数字;同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。
下面是一个更复杂的表达式:\(?0\d{2}[) -]?\d{8}。
这个表达式可以匹配几种格式的电话号码,像(010)88886666,或022-22334455,或02912345678等。
我们对它进行一些分析吧:
分枝条件
不幸的是,刚才那个表达式也能匹配010)12345678或(022-87654321这样的“不正确”的格式。要解决这个问题,我们需要用到分枝条件。正则表达式里的分枝条件指的是有几种规则,如果满足其中任意一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。听不明白?没关系,看例子:
0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。
\(0\d{2}\)[- ]?\d{8}|0\d{2}[- ]?\d{8}这个表达式匹配3位区号的电话号码,其中区号可以用小括号括起来,也可以不用,区号与本地号间可以用连字号或空格间隔,也可以没有间隔。你可以试试用分枝条件把这个表达式扩展成也支持4位区号的。
\d{5}-\d{4}|\d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5}|\d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。
分组
我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定子表达式(也叫做分组),然后你就可以指定这个子表达式的重复次数了,你也可以对子表达式进行其它一些操作(后面会有介绍)。
(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。要理解这个表达式,请按下列顺序分析它:\d{1,3}匹配1到3位的数字,(\d{1,3}\.){3}匹配三位数字加上一个英文句号(这个整体也就是这个分组)重复3次,最后再加上一个一到三位的数字(\d{1,3})。
不幸的是,它也将匹配256.300.888.999这种不可能存在的IP地址。如果能使用算术比较的话,或许能简单地解决这个问题,但是正则表达式中并不提供关于数学的任何功能,所以只能使用冗长的分组,选择,字符类来描述一个正确的IP地址:((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)。
理解这个表达式的关键是理解2[0-4]\d|25[0-5]|[01]?\d\d?,这里我就不细说了,你自己应该能分析得出来它的意义。
反义
有时需要查找不属于某个能简单定义的字符类的字符。比如想查找除了数字以外,其它任意字符都行的情况,这时需要用到反义:
常用的反义代码
\W匹配任意不是字母,数字,下划线,汉字的字符
\S匹配任意不是空白符的字符
\D匹配任意非数字的字符
\B匹配不是单词开头或结束的位置
[^x]匹配除了x以外的任意字符
[^aeiou]匹配除了aeiou这几个字母以外的任意字符
例子:
\S+匹配不包含空白符的字符串。
<a[^>]+>匹配用尖括号括起来的以a开头的字符串。
后向引用
使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。
后向引用用于重复搜索前面某个分组匹配的文本。例如,代表分组1匹配的文本。难以理解?请看示例:
\b(\w+)\b\s+\b可以用来匹配重复的单词,像go go, 或者kitty kitty。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容(也就是前面匹配的那个单词)()。
你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s+\k<Word>\b。
使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:
常用分组语法
我们已经讨论了前两种语法。第三个(?:exp)不会改变正则表达式的处理方式,只是这样的组匹配的内容不会像前两种那样被捕获到某个组里面,也不会拥有组号。“我为什么会想要这样做?”——好问题,你觉得为什么呢?
零宽断言
接下来的四个用于查找在某些内容(但并不包括这些内容)之前或之后的东西,也就是说它们像\b,^,$那样用于指定一个位置,这个位置应该满足一定的条件(即断言),因此它们也被称为零宽断言。最好还是拿例子来说明吧:
(?=exp)也叫零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc。
(?<=exp)也叫零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading。
假如你想要给一个很长的数字中每三位间加一个逗号(当然是从右边加起了),你可以这样查找需要在前面和里面添加逗号的部分:((?<=\d)\d{3})+\b,用它对1234567890进行查找时结果是234567890。
下面这个例子同时使用了这两种断言:(?<=\s)\d+(?=\s)匹配以空白符间隔的数字(再次强调,不包括这些空白符)。
负向零宽断言
前面我们提到过怎么查找不是某个字符或不在某个字符类里的字符的方法(反义)。但是如果我们只是想要确保某个字符没有出现,但并不想去匹配它时怎么办?例如,如果我们想查找这样的单词--它里面出现了字母q,但是q后面跟的不是字母u,我们可以尝试这样:
\b\w*q[^u]\w*\b匹配包含后面不是字母u的字母q的单词。但是如果多做测试(或者你思维足够敏锐,直接就观察出来了),你会发现,如果q出现在单词的结尾的话,像Iraq,Benq,这个表达式就会出错。这是因为[^u]总要匹配一个字符,所以如果q是单词的最后一个字符的话,后面的[^u]将会匹配q后面的单词分隔符(可能是空格,或者是句号或其它的什么),后面的\w*\b将会匹配下一个单词,于是\b\w*q[^u]\w*\b就能匹配整个Iraq fighting。负向零宽断言能解决这样的问题,因为它只匹配一个位置,并不消费任何字符。现在,我们可以这样来解决这个问题:\b\w*q(?!u)\w*\b。
零宽度负预测先行断言(?!exp),断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字;\b((?!abc)\w)+\b匹配不包含连续字符串abc的单词。
同理,我们可以用(?<!exp),零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字。
一个更复杂的例子:(?<=<(\w+)>).*(?=<\/>)匹配不包含属性的简单HTML标签内里的内容。(?<=<(\w+)>)指定了这样的前缀:被尖括号括起来的单词(比如可能是<b>),然后是.*(任意的字符串),最后是一个后缀(?=<\/>)。注意后缀里的\/,它用到了前面提过的字符转义;则是一个反向引用,引用的正是捕获的第一组,前面的(\w+)匹配的内容,这样如果前缀实际上是<b>的话,后缀就是</b>了。整个表达式匹配的是<b>和</b>之间的内容(再次提醒,不包括前缀和后缀本身)。
注释
小括号的另一种用途是通过语法(?#comment)来包含注释。例如:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)。
要包含注释的话,最好是启用“忽略模式里的空白符”选项,这样在编写表达式时能任意的添加空格,Tab,换行,而实际使用时这些都将被忽略。启用这个选项后,在#后面到这一行结束的所有文本都将被当成注释忽略掉。例如,我们可以前面的一个表达式写成这样:
(?<=# 断言要匹配的文本的前缀 <(\w+)> # 查找尖括号括起来的字母或数字(即HTML/XML标签) ) # 前缀结束 .* # 匹配任意文本 (?=# 断言要匹配的文本的后缀 <\/\1> # 查找尖括号括起来的内容:前面是一个"/",后面是先前捕获的标签 ) # 后缀结束
贪婪与懒惰
当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配。
有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。现在看看懒惰版的例子吧:
a.*?b匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)。
处理选项
上面介绍了几个选项如忽略大小写,处理多行等,这些选项能用来改变处理正则表达式的方式。下面是.Net中常用的正则表达式选项:
一个经常被问到的问题是:是不是只能同时使用多行模式和单行模式中的一种?答案是:不是。这两个选项之间没有任何关系,除了它们的名字比较相似(以至于让人感到疑惑)以外。事实上,为了避免混淆,在最新的 JavaScript 中,单行模式其实名叫 dotAll,意为点可以匹配所有字符,然而在指定该选项时,用的还是 Singleline 的首字母 s.
*请认真填写需求信息,我们会在24小时内与您取得联系。