JS:正则表达式

  正则表达式描述了一种字符串匹配的模式(pattern),可以用来检查一串是否含有某种子串、将匹配的字串替换或者从某个串重取出符合某个条件的子串等。补充一句,这是前端必学的技能。

正则表达式由两种基本字符类型组成:

  原义文本字符  => 比如"abc"就是原义文本字符,只是匹配"abc"这个字符串,当我们想匹配一个字符串中包含abc的时候,就需要用元字符。

  元字符 => 构建一个简单的类,学过面向对象的人应该都很清楚,类是指符合某些特性的对象,一个泛指,而不是特指某个字符,比如[abc]把字符a或b或c归为一类,只要含有其中一个的都会被匹配出来

举个例子:

字符类

replace这个函数的第一个参数可以是正则表达式也可以是字符串,都起到匹配作用,后面是将匹配到的内容替换,返回一个新字符串,原本的字符串并不会改变,那个g是global全局的意思,没有加的话只会匹配第一次,

那我们要取不是a或b或c的就加个^

再举个常用的,\b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。

\B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er',大小写在正则表达式基本是取反的意思。常用元字符链接:http://www.runoob.com/regexp/regexp-metachar.html

范围类 

使用[a-z]来连接两个字符表示从a到z的任意字符,这是个闭区间,所以包含a和z本身

默认情况下,正则表达式不是有区分大小写的,在g后面加个i(ignore Case)忽略大小写:

当然数字也是可以的:

当你想把里面的-都匹配到的话就可以加个0-9-,

one of,只要其中一个就可以,这边推荐一个可以看正则表达式的逻辑的网站:https://regexper.com/

^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。

$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。

所以我们经常用^表示开头,$表示结尾看下一个例子:

上面我们用了g(global)全局匹配,i(ignore Case)忽略大小写,还有个m(Multiline)将下一行重新开始匹配,不然换行也是个字符\n。

没有添加m的情况

添加m的情况

 预定义字符

我们刚才就用过了预定义字符,就是正则自带的字符,比如刚才用的\b,\d。

量词

我们喜欢匹配一个字符串中含有5个数字\d\d\d\d\d,这样是可以,但有量词就比较简单了,匹配5次的正则可以写成\d{5},还有一些量词:

\d{0,10}\w\b\d?:

贪婪模式和非贪婪模式

默认情况下是贪婪模式,就是尽可能多的匹配,

上面的正则匹配三个数字为一组的,默认情况下,尽可能多的匹配,把123456本来应该改成xx现在改成x,切换成非贪婪模式也很简单,在量词后加上?就可以了:

分组

当我们这样写:one{2} 表达的是on匹配一次e匹配两次,但我们想要one一整个匹配两次,可以用()来分组:

在平时编程时候经常在if里面用||和&&,正则也有,我们看个例子:

用的更高级点:

反向引用

直接看例子:

上面说过用()来分组,正则里面分组后还自动帮我们保存在变量里面了,$1表示第一个分组,顺序从左到右,当你没有分组时,$是没有值的,会被当作一个字符串来处理,当你不需要某些分组时,可以这样写(?:表达式)。

前瞻

 正则表达式从文本头部向尾部开始解析,文本尾部方向称为“前”,前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言,反之,后顾/后瞻方向相反,javascript不支持后顾

语法结构:

正向前瞻exp(?=assert) => exp是一个正则,assert也是一个正则,相当于符合两个正则

负向前瞻exp(?!assert) => 同理要符合exp但不能符合assert,看例子

\w(?=\d)匹配的是一个单词字符(数字也算是单词字符)后面必须加上一个数字,因为3后面没有数字所以不能匹配

JS对象属性

JavaScript中正则的test和exec方法

我们先看个例子:

 

 

 

 

 

为什么会匹配错误呢,其实这是符合的,但由于lastIndex在作怪,但我们每次test后lastIndex都会记住当前的下标,所以第一次成功,下一次的下标后面就没有字符,就重置为0,并返回false,还有个需要注意的是,在非全局下lastIndex是不生效的。

现在懂了吧,每次对象的lastIndex都会记住上一次test后的下标.

看一段代码:

let reg1 = /\d(\w)(\d)/;
let st = '$a1b2c3d4';

let result = reg1.exec(st);


console.log(reg1.lastIndex + '\t' + result.index + '\t' + result.toString());

打印结果:"0  2 1b2,b,2"

由于不是全局的所以lastIndex不生效,exec返回一个结果数组,第一个参数是被匹配到的第一个字符的下标,第二个是输出正则里面分组的参数,就是被()抱住的。

再看一段代码:

let reg1 = /\d(\w)(\d)/g;
let st = '$a1b2c3d4e5f6';

let result;

while(result = reg1.exec(st))
  {
    console.log(reg1.lastIndex + '\t' + result.index + '\t' + result.toString());
  }

结果是:

  • "5  2 1b2,b,2"
  • "9  6 3d4,d,4"
  • "13 10  5f6,f,6"

同样的第一次匹配到1b2,2的下标是5,这是lastIndex被赋值5,用于下次继续匹配,1b2的1的下标是2,后面的b,2是分组,这个可以看自己是否需要,下面两次一样的思路。

 String.protatype.search(reg);

用于检索字符串中指定的字符串,或检索与正则表达式相匹配的子字符串

方法返回第一个匹配结果index,查找不到返回-1

search()方法不执行全局匹配,它将忽略标志g,并且总是从字符串的开始检索

String.propotype.match()

可以包含标志g,也可以不包含,两种不同用法返回的值也不同。

可以看出非全局调用时,返回匹配到的字符串和分组的值,还有匹配到字符串的第一个字符的下标,还有对stringObject的引用,简单来说就是返回当前值,可以返回值和正则表达式下的exec非全局的返回值一样

全局调用

 执行全局检索,找到字符串中的所有匹配子字符串

  没有找到任何匹配的字串,则返回null

  如果找到了一个或多个匹配子串,则返回一个数组

数组元素中存放的是字符串中所有的匹配字串,而且页没有index属性或input属性

这里需要区分的是这里的全局匹配的lastIndex是为0的,而上面每次匹配都会保存,看你要在什么情况下使用。

接下来是很常用的分隔符split

接下来是我们上面调试用的string.replace,不会该原字符串,会返回一个新字符串

前两个我们前面用过,这次讲第三个的用法,相当于回调,每次匹配时都会回调

function有四个参数:

1.匹配字符串

2.正则表达式分组内容,没有分组则没有该参数,第三个参数就变成第二个参数

3.匹配项在字符串中的index

4.原字符串

现在所有信息你都可以拿到了。

现在看下有分组的:

现在差不多正则表达式都完了,可以多练习下。推荐两个网站:查看正则的逻辑https://regexper.com/

查看正则匹配的字符:http://tool.oschina.net/regex/

posted @ 2018-03-07 22:10  await  阅读(567)  评论(0编辑  收藏  举报