Skip to the content.

正则表达式


定义

又称规则表达式 ———— 则通常被用来检索、替换那些符合某个模式(规则)的文本。

正则只能作用在字符串上

基础学习

定义规则表达式

  1. 字面量形式

    /规则表达式/[修饰符]

    规则可以是普通的字符串 斜杠中直接放入字符串,不需要加引号

     let re = /abc/
        
     console.log(re)//  /abc/
    
  2. 利用构造函数

    new RegExp(规则(字符串),[修饰符])

     let re2 = new RegExp('abc')
    
     console.log(re2)//   /abc/
    
  3. 区别:

    当规则存在变量中时,需要使用构造函数的形式

     let s = 'peace'
     let re2 = new RegExp(s)
    
     console.log(re2)// /peace/
    

转义字符

转义符 \

let str = 'miaov\'ketang';
console.log(str);// miaov'ketang

'—-一个单引号 \d —–代表数字 " —–一个单引号

或的意思

[ ] [1-40]匹配的是1,2,3,4,0并不是1~40

let str = 'h1hj33jhjgh3j2323hjh12k'

let re = /[3kh]/g;
let re2 = /[1-5]+/g;//表示匹配1~5

console.log(str.match(/3|k|h/g))
console.log(str.match(re))
console.log(str.match(re2))//["1", "33", "3", "2323", "12"]

修饰符

  1. g — 全局匹配

     /\d/g  ---  全局搜索数字,从头到尾搜索,中间不停止
    
  2. i — 忽略大小写

     /m/i  ---  M和m都能找到
    

元字符

  1. \d — 数字 , 等价于 [0-9]。

     /\d/  ---  从头到尾搜索,有一个满足就停止
    
  2. \D — 匹配一个非数字字符。等价于 [^0-9]。
  3. \f — 匹配一个换页符。等价于 \x0c 和 \cL。
  4. \n — 匹配一个换行符。等价于 \x0a 和 \cJ。
  5. \r — 匹配一个回车符。等价于 \x0d 和 \cM。
  6. \s — 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
  7. \S — 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
  8. \t — 匹配一个制表符。等价于 \x09 和 \cI。
  9. \v — 匹配一个垂直制表符。等价于 \x0b 和 \cK。
  10. \w — 匹配字母或数字或下划线或汉字。等价于’[A-Za-z0-9_]’。
  11. \W — 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]‘。
  12. ? — 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 “oooo”,’o+?’ 将匹配单个 “o”,而 ‘o+’ 将匹配所有 ‘o’。
  13. . — 匹配除 “\n” 之外的任何单个字符
  14. x y — 匹配 x 或 y。例如,’z food’ 能匹配 “z” 或 “food”。’(z f)ood’ 则匹配 “zood” 或 “food”。
  15. [xyz] — 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。
  16. [^xyz] — 负值字符集合。匹配未包含的任意字符。例如, ‘[^abc]’ 可以匹配 “plain” 中的’p’、’l’、’i’、’n’。
  17. [a-z] — 字符范围。匹配指定范围内的任意字符。例如,’[a-z]’ 可以匹配 ‘a’ 到 ‘z’ 范围内的任意小写字母字符
  18. [^a-z] — 负值字符范围。匹配任何不在指定范围内的任意字符。例如,’[^a-z]’ 可以匹配任何不在 ‘a’ 到 ‘z’ 范围内的任意字符。

限定符

* — 可以不出现,最多不限 {0,}

定位符

定位符使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。

定位符用来描述字符串或单词的边界,^ 和 $ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。

^ —– 匹配输入字符串开始的位置 $ —– 匹配输入字符串结尾的位置 \b —- 匹配单词的开始或结束,匹配一个字边界,即字与空格间的位置,就是\w的左边或右边如果不是\w,就是一个边界。书写位置很重要 abcdefg /\babc/往后匹配,/efg\b/从边界往前匹配 \B —- 非字边界匹配

let str = 'w1tw23tw456tw7890tw12345twt';

let re = /\d/;
let re2 = /w\dt/g;//一次
let re3 = /w\d+t/g;//最少一次
let re4 = /w\d*t/g;//不限
let re5 = /w\d?t/g;//最多一次

console.log( str.match(re) )//["1", index: 1, input: "w1tw23tw456tw7890tw12345twt"]
console.log( str.match(re2) )//["w1t", "w23t", "w456t", "w7890t", "w12345t"]
console.log( str.match(re3) )//["w1t", "w23t", "w456t", "w7890t", "w12345t"]
console.log( str.match(re4) )//["w1t", "w23t", "w456t", "w7890t", "w12345t", "wt"]
console.log( str.match(re5) )//["a1f", "a7f", "a2f", "af"]

正则方法

test(str)

作用:用来检测指定的字符串是否符合正则的规则 语法:regExObj.test(string) 参数:被检索的字符串 返回值:true或false

let re = /123/
//定义的正则规则
text.oninput = function(){
	if(re.test(this.value)){
		warn.innerHTML = '有123'
	}else{
		warn.innerHTML = '没123'
	}
}
test()记录上一次执行位置
let str = '123456789'

let re = /\d{5,5}/g

console.log(re.test(str))//true
console.log(re.lastIndex)//5

console.log(re.test(str))//false
console.log(re.lastIndex)//0

//-----------解决办法---------------------

console.log(re.test(str))//true
re.lastIndex = 0;
console.log(re.test(str))//true
以上代码第一次执行的时候,匹配的是12345,test会记录该次执行的位置5
第二次执行的时候,test会从第5位开始查找,但是最少要5位,6789只有4位,不满足,返回false

match()

作用:检索指定字符串或正则表达式匹配到的字符串 语法:string.match( 正则|指定字符 ) 参数:字符串或正则表达式 返回值:有匹配到的返回到一个数组中,没有返回null

let str = 'wo1r23kd45Pe67ac890e';

let re = /\d/;

console.log( str.match(re) )
//["1", index: 2, input: "wo1r23kd45Pe67ac890e"]
let str = 'wo1r23kd45Pe67ac890e';

let re2 = /\d/g;
let re3 = /\d+/g;

console.log( str.match(re2) )
//["1", "2", "3", "4", "5", "6", "7", "8", "9" , "0"]

console.log( str.match(re3) )
//["1", "23", "45", "67", "890"]
string.search( string re );

作用:检索指定字符串或正则表达式匹配到的字符串首次出现的位置 语法:string.search( 正则|指定字符 ) 参数:字符串或正则表达式 返回值:有匹配到的返回指定字符或正则出现的位置 number

作用类似于字符串方法的indexOf,但是更强大,参数除了可以是指定字符外,还可以是正则表达式
let str = 'w1tw23tw456tw7890tw12345twt';

console.log( str.indexOf('0') )//16

let re = /0/
console.log( str.search('0') )//16----可以是字符串
console.log( str.search(re) )//16----也可以是正则

replace()

用来替换字符串中的某些符合规则的字符 语法:string.replace(string|regexObj,string|function) 参数: 1. 第一个参数:字符串或正则表达式 2. 第二个参数:字符串或函数 返回值:

//将匹配字符替换为str-----第二个参数为字符串
string.replace(string|regexObj,str)

//将匹配字符替换为str-----第二个参数为函数
string.replace(string|regexObj,function($0,$1,$2){
    //$0:满足规则的每个字符
    //$1:满足规则的每个字符所在的位置
    //$2:被检索的完整字符串
    return '*'//将满足规则的字符替换为*,return后的字符就是要替换的字符

})
let str = '1asd2'

let re = /(\d)\D+(\d)/g;

let str2 = str.replace(re,function(...data){
	console.log(data)
    //["1asd2", "1", "2", 0, "1asd2"]
    //   $1,    $2,  $3, $4,   $5
})
let str = 'a23ba456ba7b'

let re = /(\d)\D+(\d)/g;

let str2 = str.replace(re,function(...data){
	console.log(data)
	//["3ba4", "3", "4", 2, "a23ba456ba7b"]
	//["6ba7", "6", "7", 7, "a23ba456ba7b"]
	//
})

运算符优先级

转义符

圆括号和方括号

限定符

定位点和序列(即:位置和顺序)

替换

分枝条件

\d{5}-\d{4} \d{5}这个表达式用于匹配美国的邮政编码。美国邮编的规则是5位数字,或者用连字号间隔的9位数字。之所以要给出这个例子是因为它能说明一个问题:使用分枝条件时,要注意各个条件的顺序。如果你把它改成\d{5} \d{5}-\d{4}的话,那么就只会匹配5位的邮编(以及9位邮编的前5位)。原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。

分组()

捕获

() 的意思是表示中间是整体

有()默认捕获分组信息,

(?:/\d/g) 不捕获分组信息,也不分配组hao

let t1 = '2017---8-----25'
//-----------默认捕获---------------
let re = /(\d+)\D+\d+\D+\d+/g;
t1.replace(re,(...data)=>{
	console.log(data)//["2017---8-----25", "2017", 0, "2017---8-----25"]
	return data[1]+''+data[3]+''+data[5]+''
})

//------------设置不捕获-----------
let re1 = /(?:\d+)\D+\d+\D+\d+/g;
t1.replace(re1,(...data)=>{
	console.log(data)//["2017---8-----25", 0, "2017---8-----25"]
	return data[1]+''+data[3]+''+data[5]+''
})

//?:    设置不捕获,分组匹配到的字符不会记录

分组后向引用

后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本

如:(\w+){2}a\1—-\1代表的就是括号(\w+)搜索到的字符,可以在后面复用。

零宽断言

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

零宽度正预测先行断言,它断言自身出现的位置的后面能匹配表达式exp。比如\b\w+(?=ing\b),匹配以ing结尾的单词的前面部分(除了ing以外的部分),如查找I'm singing while you're dancing.时,它会匹配sing和danc

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

零宽度正回顾后发断言,它断言自身出现的位置的前面能匹配表达式exp。比如(?<=\bre)\w+\b会匹配以re开头的单词的后半部分(除了re以外的部分),例如在查找reading a book时,它匹配ading

(?!exp) 匹配后面跟的不是exp的位置

零宽度负预测先行断言,断言此位置的后面不能匹配表达式exp。例如:\d{3}(?!\d)匹配三位数字,而且这三位数字的后面不能是数字

(?< !exp) 匹配前面不是exp的位置

零宽度负回顾后发断言来断言此位置的前面不能匹配表达式exp:(?<![a-z])\d{7}匹配前面不是小写字母的七位数字

贪婪模式和懒惰模式

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符

let t1 = 'abacbacob';

//找到a开头b结尾的

let re = /a.*b/g;//贪婪模式:尽最大可能找到最大范围的字符,从字符串尾部开始向前搜索
console.log( t1.match(re)) //["abacbacob"]

let re2 = /a.*?b/g//懒惰模式:从前往后搜索,挨个检索
console.log( t1.match(re2)) //["ab", "acb", "acob"]

//语法:在相应的正则规则后加?

自定义模板引擎

通过正则检索到对应的特殊字符,对里面的变量进行replace成定义数据的对应变量

<div id="box"></div>

//定义模板字符串
let html = `
<p id="op">@@title@@</p><p id="ap"><div class="hob">@@list1@@</div><div class="hob">@@list2@@</div><div class="hob">@@list3@@</div></p>
`

//对应数据
let obj = {
	title:'谦哥的三大爱好:',
	list1:'抽烟',
	list2:'喝酒',
	list3:'烫头'
}

//检索正则
let re = /@@(.+?)@@/g;
//此处要有?,执行懒惰模式,否则会匹配从@@开始到@@结束的整个字符串
//@@title@@</......ass="hob">@@list3@@

//检索后replace函数
function diy(){
	return html.replace(re,($0,$1,$2)=>{
		console.log($1)
		return obj[$1]
	})
}

box.innerHTML = diy();

/*
谦哥的三大爱好:
抽烟
喝酒
烫头
*/