Maison> interface Web> js tutoriel> le corps du texte

带你吃透正则

小云云
Libérer: 2017-11-20 13:33:44
original
1327 Les gens l'ont consulté

正则表达式,又称规则表达式,英文名为Regular Expression,在代码中常简写为regex、regexp或RE,是计算机科学的一个概念。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。网站上有很多关于正则的视屏教程,但是往往收获并不多,都是蜻蜓点水,一点就过。事实上,正则用处真的超级大,比如匹配innerHTML的内容,以及表单验证,也是非他莫属。这里,我结合js,对正则进行一个简单的介绍吧。

js与正则的关系

在js中定义一个正则有两种方法,一个是实例化,一个是字面量。 分别看一下:

//字面量 var re = /\w+/; //这两者等价 //实例化 var re = new RegExp('\\w+');
Copier après la connexion

如果想添加一些flags也是没有问题的。 比较常用的flag有。/i,/g,/ig,/m.

/i (忽略大小写,ignore) /g (全文查找出现的所有匹配字符,global) /m (多行查找,multiLine) /ig(全文查找、忽略大小写,ignore+global)
Copier après la connexion

所以, 使用flag之后可以这样写.

var reg = ^\d{5,12}\i$ ;//表示忽略大小写,匹配; //或者 var reg = new RegExp(^\d{5,12}\i$);
Copier après la connexion

正式入门正则

正则其实就是用来匹配字符串的。他用一个简洁表达了,完成了你需要写很多代码的事,就和md(markdown)语法是一个道理。 用的人多了,自然成标准,这也是规则吧。

正则预定字符

预定字符,就是用程序比较难表达的一些字符,比如回车键,tab键(通过空格来区分达到的效果). 常用的有:

字符

效果

\t 制表符,其实就是一个“Tab”键 \r 回车符,如果你使用过word应该之后,在一个段落后面那个东西吧。 :) \n 换行符,他和\r是有故事的,等下说,我们继续
Copier après la connexion

恩,大部分就是这几个了。 上面提到 \r和\n,他们到底有什么却别。 没错,看字面量,感觉return 不就是换行吗? 其实,这样说没错,但是得区分系统,在Unix为扩展的系统,在每行的结尾只有"\n",而在window下则是:"\r\n"(顺序不能换). 所以,为了解决系统的差异,就出现了两种: \r || \n. 所以一般,我们匹配换行需要使用.\r||\n一起使用.

var reg = /[\r\n]/g;

这样就能保证系统的兼容性.

字符类

所谓的字符类同样也是将你平常要花很多时间做出来的,集成为一个简洁表达。(相当于写库)。 常用的字符类有如下几个。

字符

效果

. 匹配换行符以外的任意字符

\d 匹配所有数字 \D 匹配非数字 \s 匹配一个空格符 \S 匹配非空格 \w 匹配字母数字下划线=>其实就是匹配单词word(简单易懂) \W 匹配!字母数字下划线=>就是不匹配单词
Copier après la connexion

来我们看几个例子

console.log(/\s+/.test(" ")); //true console.log(/\d+/.test("1234231")); //true console.log(/\D+/.test(" ")); //true
Copier après la connexion

其他的如上。

锚字符

这个应该算是正则里面,取名最好理解的一个。使用正则就是停船一样,你需要设置你停的位置,我也需要设置我的边界。 常用的有一下几个:

锚字符

效果

^ 匹配字符串的开头,在多行检索中,匹配一行的开头

$ 匹配字符串的结尾,在多行检索中,匹配一行的结尾

\b 匹配一个单词的边界

\B 匹配非单词边界

这几个应该算是我平常用的最多的几个吧。 如果你想匹配整个字符串,就可以组合使用"^ $";

var reg = /^\d+$/; //匹配整个字符串为数字

量词字符

“望文生义”,这类字符使用来限定某某出现的次数的。 常用的有:

代码 / 语法

说明

* 重复零次或更多次

+ 重复一次或更多次

? 重复零次或一次

{n} 重复n次

{n,} 重复n次或更多次

{n, m} 重复n到m次

这个应该不用多说了。 直接看例子吧

console.log(/^\d+$/.test("123")); //true
Copier après la connexion

上面说了这么多内置的字符,那我想使用特定字符类怎么办嘞。其实也很简单。使用"“转义字符。 比如我想匹配大括号.”{}".我可以这样用:

console.log(/\{.+\}/.test("{123}")); //true
Copier après la connexion

但事实上,量词还分为3种,有贪婪量词,惰性量词,支配性量词。 区分的依据是根据引擎的解析不同而形成。 贪婪量词 这类量词指的就是上文所说的: *,+,?。 他的匹配方法就是,全文匹配,如果不成功,则,将末尾的最后一个字符减去,再匹配,如果还不成功,则,再减一次。只到为0。 接着,往中间移动一位,再进行匹配,同样的匹配模式。

console.log(/.+/.test("abcd")); //true
Copier après la connexion

惰性量词使用方法: 基本量词 ? 该量词和贪婪量词就像,一个是消极怠工,一个是积极工作。 惰性量词一开始只会匹配一个字符,如果不成功,则在进行匹配。

console.log(/\d+?/.test("1fjkdf")); //true
Copier après la connexion

这里阐述一些惰性和贪婪匹配的区别。 我们也通常把惰性称为最少重复匹配。 举个例子: 我们现在需要匹配blablablabla. 中的b~a间的词。 使用贪婪匹配:

var str = "blablablabla"; console.log(str.match(/(b.*a)/g)); //["blablablabla"]
Copier après la connexion

我们最少重复匹配(惰性匹配)

console.log(str.match(/(b.*?a)/g)); //["bla", "bla", "bla", "bla"]
Copier après la connexion

支配性量词使用方法: 基本量词 +; 该量词就是只匹配一次,如果不符合则不匹配。 但是由于js不支持,所以,这里也不做过多的介绍。

正则: /\d*+/;

其实上面只要留个印象就可以,只有当你真正使用的时候,你才会有感触。 OK!!!基本内容说完了,现在轮到真正的进阶,big boom~

中括号的用法

我们从小学学过来,老师告诉我们,我们使用括号有3种,一个是( ),一个是[],一个是{}. 而在正则里面,大括号已经被量词字符给强占了,只剩下[]和(). 这里我们来说一下,中括号. [],在正则里面代表的是一个单元字符,或者我宁愿叫他"或"括号. 因为他起到的主要作用就是,你可以匹配这个或者匹配那个或者… 吃个栗子:

var reg = /[abc]/; console.log(reg.test("a")); //true
Copier après la connexion

可以看出,reg可以匹配 a|b|c. 平常使用的时候,可以直接向一个字符使用就可以了。 异或表达 这里会出现一个问题,比如,我不想匹配a,b,c中的任意一个该怎么办呢? 其实,只需要在"[]“里面加上”^"即可。

console.log(/[^abc]/.test("c")); //false
Copier après la connexion

范围字符范围字符,就是可以省略一些周所周知的。 比如匹配26英文字母可以直接使用:a-z. 因为我们已经都知道了这个的意义。 其实,上面所说的字符类完全就可以使用中括号来代替。

\d => [0-9] \w => [0-9a-zA-Z_] \S => [^\t\n\x0B\f\r] (\f标识分页符)
Copier après la connexion

...

另外这个范围字符还有一个好处,就是匹配中文。(电脑都是外国人发明的呀。)

console.log(/[\u4e00-\u9fa5]{1}/.test("艹")); //true
Copier après la connexion

这就是中括号的常用用法。

小括号使用

小括号的主要作用其实就是分组。平常是用来提取匹配到的字符串。 分组使用 使用()对内容进行区分。

console.log(/(jimmy)+/.test("jimmy")); //true
Copier après la connexion

而且,配合使用match方法,可以获得匹配到的内容.(这里不加括号也是可以的).

var name = "My name is Jimmy"; console.log(name.match(/(Jimmy)/g)); //["Jimmy"]
Copier après la connexion

需要注意在括号里面写正则和没有括号的时候,是没有区别的。我们可以在()内嵌套你想加的。(如果你想嵌套()的话,Sorry,这样并没有什么卵用).

var name = "My name is Jimmy Jimy"; console.log(name.match(/(Jimm?y)/g)); //["Jimmy", "Jimy"]
Copier après la connexion

候选(或)这个就相当于将括号加上一个或的功能. 即,在()里面使用"|"进行分隔。

var name = "My name is Jimmy sam"; var reg = /(jimmy|sam)+?/ig; console.log(name.match(reg)); //["jimmy","sam"]
Copier après la connexion

反向引用这个名字我真心不理解,什么"反向"… 我宁愿叫做,给分组加上标识符。这个的主要功能,就是给匹配到的小括号加上数字,来表明他是第几个匹配到的。如果不加,则默认从左到右的顺序为1,2,3…

var reg = /(100)\1/; var reg2 = /(100)(99)(101)\1\2\3/; //1=>100,2=>99,3=>101
Copier après la connexion

在js中,通常是和replace搭配,才有威力。

var reg = /(100) (99)/; var str = "100 99"; console.log(str.replace(reg,"$2 $1")); //99 100
Copier après la connexion

总而言之, 小括号就是让你使用分组的匹配. 说回来,分组有什么用呢? 实际上就是让你的正则看起来更短而已. 看个demo你就懂分组的意义了:

var str = "name jimmy"; console.log(str.match(/\b(\w+)\b\s+\1\b/)); // 这里的\1 实际上就是前面的(\w+) //得到的结果为 null. 因为name 不能匹配到jimmy所以为null var str = "jimmy jimmy"; console.log(str.match(/\b(\w+)\b\s+\1\b/)); //得到的结果为 jimmy。 因为/w匹配到的为jimmy,所以为jimmy
Copier après la connexion

上面那种方法叫做后向引用. 另外, 我们还可以显示的使用命名. 即: \b(? \w+)\b\s+\b\kfetchWord\b 这样,就可以达到, 内部正则的复用. 不过, 对不起, 在js中,只支持数组分组, 即, 按顺序分配序号。和上面demo一样. 不过在perl 系列的正则中是使用(?P< xx>) 和 \g

非捕获分组

我们直接使用 "(…)"进行的匹配是捕获分组。 我们来说一下什么叫 捕获 . 上文中我们使用match进行正则匹配,而返回的数组中的元素就是通过正则捕获的内容。 这就叫捕获。 那这里的非捕获,是什么意思呢? 其实很简单,就是通过match不会匹配到内容。但还是可以起到分组的效果。 格式为: (?:xxx) 它最常用的地方就是匹配html.

var str=` 
`; var reg = //gi; console.log(str.match(reg));
Copier après la connexion

大家可以去试一试,说到正则匹配,我还有一个想说的,就是上文所说的惰性匹配(最少重复)和贪婪匹配。 可以看到 “/< div(?:.|\r|\n)*div>/gi” 我这里使用的是贪婪匹配。他的结果是,尽量匹配到最外层的< /div>标签。 即上面的结果为:

Copier après la connexion

可以看出,贪婪匹配,对于两个重复的/div 他会匹配到最外一层。 那我们使用惰性匹配试一试。 /< div(?:.|\r|\n)*?div>/gi 得到的结果为:

Copier après la connexion

可以看出少了一个< /div>,原因就是,惰性匹配尽量只会匹配到第一个重复的< /div>上面的。 所以,总结一下,在使用正则匹配的时候需要搞清楚到底什么时候用惰性,什么时候用贪婪,这点很重要。 贪婪会匹配最外层,惰性会匹配最里层。

前瞻(零宽断言)

前瞻分为正向前瞻和反向前瞻。(由于js只支持前瞻,所以后瞻只会提一下)。 他的作用就是,在匹配的字符后面,断言说后面一定符合我的正则。 (好饶~~) 算了,先说一下基本格式吧。

正则

名称

作用

(?=exp) 正向前瞻 匹配exp前面的位置

(?!exp) 反向前瞻 匹配后面不是exp的位置

(?<=exp) 正向后瞻 匹配exp后面的位置

(?< !exp) 反向后瞻 匹配后面不是exp的位置

看不懂了吧,我们来看一下详细的内容。 for instances:

var str = "happied boring"; var reg1 = /happ(?=ied)/g; var reg2 = /bor(?!ied)/; console.log(str.match(reg1)); //["happ"] console.log(str.match(reg2)); //["bor"]
Copier après la connexion

从这个例子可以很容易看出前瞻后瞻到底是什么了。 回到上面的匹配html的例子。 这里我们有个需求,即只留下img标签,那么就可以使用前瞻.

var str=` 
`; var reg = /<(?!img)(?:.|\r|\n)*?>/gi; console.log(str.replace(reg,"")); //得到的结果为:
Copier après la connexion

另外,零宽断言还有另外一个作用,即匹配以xxx为结尾的单词。 这时候,你的leader对你有个要求,即,jimmy呀,你把ed结尾的单词找出来哦。(好呀~) 这时候就可以使用前瞻了。

var str = "he is an interested person"; var reg = /\b\w+(?=ed\b)/ig; console.log(str.match(reg)); //["interest"]
Copier après la connexion

关于正则的内容大概就是这些了。 其实正则的学习,不是只用看就能学会的,实践才是硬道理。 通过,理论的学习,在加上踩过的坑,自然会对正则有着莫名的好感。 不过,大神就是大神,取名字就是这么别扭。 什么 零宽断言,前瞻,后瞻,反向引用 blablabla… 在理解的同时可以根据自己的理解给这些名词冠上自己的idea.我这里只是 正则的冰山一角,正则在任意一门语言内,用处都是超级大的。

以上这些分享希望对大家有帮助。

相关推荐:

PHP正则表达式合集

最实用的十个PHP正则表达式

js 常用正则表达式有哪些

完美实现身份证校验 js正则的方法

常用的正则表达式汇总

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!