Skip to content

正则表达式

比较好的学习资料:
正则表达式30分钟入门教程
简介 | 正则表达式30分钟入门教程
[JS相关的正则函数]
实用网站:Regex Vis

元字符

  • 元字符\b 匹配单词开头或结尾,并不匹配这些单词分隔字符中的任何一个,它只匹配一个位置.
js
console.log("AHello Hello!".search(/\bHello/i)) // 7
console.log('him,history,hi,high'.search(/\bhi\b/)) // 12
console.log("AHello Hello!".search(/\bHello/i)) // 7
console.log('him,history,hi,high'.search(/\bhi\b/)) // 12
  • 元字符 . :匹配除了换行符以外的任意字符
  • 元字符*: 匹配的是数量,表示*前面的字符可以重复0次或多次
  • 元字符+: 重复1次或多次
  • 元字符?: 重复0次或1次
js
console.log("hello Moxod".search(/\bMo.od\b/i)) // 6  【.代替任意字符】
console.log("hello Moooooood".search(/\bMo*d\b/i)) // 6  【*标识前一个字符重复n次】
console.log("hello".search(/m+/i)) // -1  【m重复1次】
console.log("hello m".search(/m+/i)) // 6  【m重复1次的位置】
console.log("hello".search(/m*/i)) // 0  【m重复0次或者多次】
console.log("hellom".search(/m*/i)) // 0  【m重复0次或者多次】
console.log("sexy".search(/x?/i)) // 0  【x重复0次或者1次,也就是可以有也可以没有】
console.log("sexxy".search(/x?/i)) // 0  【x重复0次或者1次,也就是可以有也可没有】
console.log("sexy".search(/x?/i)) // 0  【x重复0次或者1次】
console.log("156558".search(/1565?58/i)) // 0  【5重复0次或者1次,也就是前一个字符5可以有0个或者1个】 
console.log("1565058".search(/1565?58/i)) // -1  【5重复0次或者1次,也就是可以匹配到 15658 、15658】
console.log("15658".search(/1565?58/i)) // 0  【5重复0次或者1次,也就是可以匹配到 15658 、15658】
console.log("hello Moxod".search(/\bMo.od\b/i)) // 6  【.代替任意字符】
console.log("hello Moooooood".search(/\bMo*d\b/i)) // 6  【*标识前一个字符重复n次】
console.log("hello".search(/m+/i)) // -1  【m重复1次】
console.log("hello m".search(/m+/i)) // 6  【m重复1次的位置】
console.log("hello".search(/m*/i)) // 0  【m重复0次或者多次】
console.log("hellom".search(/m*/i)) // 0  【m重复0次或者多次】
console.log("sexy".search(/x?/i)) // 0  【x重复0次或者1次,也就是可以有也可以没有】
console.log("sexxy".search(/x?/i)) // 0  【x重复0次或者1次,也就是可以有也可没有】
console.log("sexy".search(/x?/i)) // 0  【x重复0次或者1次】
console.log("156558".search(/1565?58/i)) // 0  【5重复0次或者1次,也就是前一个字符5可以有0个或者1个】 
console.log("1565058".search(/1565?58/i)) // -1  【5重复0次或者1次,也就是可以匹配到 15658 、15658】
console.log("15658".search(/1565?58/i)) // 0  【5重复0次或者1次,也就是可以匹配到 15658 、15658】
  • .*: 表示可以前一个字符可以重复0次或多次
js
console.log(" hi后面不远处跟着一个Lucy!".search(/\bhi\b.*\bLucy\b/i)) // 1
console.log(" hi后面不远处跟着一个Lucy!".search(/\bhi\b.*\bLucy\b/i)) // 1
  • \b:匹配数字
js
console.log("哈哈1-122".search(/\d-\d/i))  // 2
console.log("哈哈1-122".search(/\d-\d/i))  // 2
  • {n}:匹配n个前一字符
  • {n,m}:匹配n-m个前一字符
  • {n,}:匹配n-无限个前一字符
  • \d+:匹配n个数字
js
console.log('012000-4560899'.search(/\d{3}-\d{7}/i)) // 3
console.log('A012000-4560899'.search(/\d+-\d+/i)) // 1
console.log('012000-4560899'.search(/\d{3}-\d{7}/i)) // 3
console.log('A012000-4560899'.search(/\d+-\d+/i)) // 1
  • \s:匹配任意的空白符、制表符tab、换行符、中文全角空格等(space)
js
console.log('aa	'.search(/\s/i))  // 2
console.log('aa	'.search(/\s/i))  // 2
  • \w: 匹配字母数字下划线汉字等(word) \w汉字一般匹配不到。不同环境、语言不一样,例如js就匹配不到
js
console.log('  s汉化'.search(/\w/i))
console.log('  s汉化'.search(/\w/i))
  • ^: 匹配位置: 字符串的开头
  • $: 匹配位置: 字符串的结尾
js
console.log(/\d/.test(1))  // true
console.log(/^d{5,12}$/.test('dddddd')) // true
console.log(/^\d{5,12}$/.test('12345')) // true
console.log(/\d/.test(1))  // true
console.log(/^d{5,12}$/.test('dddddd')) // true
console.log(/^\d{5,12}$/.test('12345')) // true
  • [x-xx]: - 表示字符区间,例如 [0-9] 代表的含意与\d就是完全一致的:一位数字。同理[a-z0-9A-Z_]也完全等同于\w(如果只考虑英文的话)。

条件、分组

  • |:分支条件
js
console.log(/^\d{5,12}|\d{2}$/.test('12')) // true
console.log(/^\d{5,12}|\d{2}$/.test('12345')) // true
console.log(/^(\d{5,12})|(\d{2})$/.test('12345')) // true
console.log(/^\d{5,12}|\d{2}$/.test('12')) // true
console.log(/^\d{5,12}|\d{2}$/.test('12345')) // true
console.log(/^(\d{5,12})|(\d{2})$/.test('12345')) // true
  • {}小括号可以进行分组
js
console.log(/^(abc){2}$/.test('abcabc')) // true  【abc重复两次】
console.log(/^(abc){2}$/.test('abcabc')) // true  【abc重复两次】

反向

大写表示非的概念

  • \D 非数字
  • \W 非字母下划线数字
  • \B 非单词开始
  • \S 非空格类
js
console.log(/^\D.*$/.test('1233')) // false  
console.log(/^\D.*$/.test('abcabc')) // true  
console.log(/^\W.*$/.test('1233a')) // false  
console.log(/^\W.*$/.test(' ')) // true  
console.log(/^\S.*$/.test('1233a')) // true
console.log(/^\S.*$/.test(' ')) // false    
console.log(/^\B.*$/.test('1233a')) // false
console.log(/^\B.*$/.test(' ')) // true
console.log(/^\D.*$/.test('1233')) // false  
console.log(/^\D.*$/.test('abcabc')) // true  
console.log(/^\W.*$/.test('1233a')) // false  
console.log(/^\W.*$/.test(' ')) // true  
console.log(/^\S.*$/.test('1233a')) // true
console.log(/^\S.*$/.test(' ')) // false    
console.log(/^\B.*$/.test('1233a')) // false
console.log(/^\B.*$/.test(' ')) // true
  • [^x]除了字母x外的字符
  • [^xyz]除了字母xyz外的字符
js
console.log(/^[^x].*$/.test('1233a')) // true
console.log(/^[^x].*$/.test('xxx')) // false
console.log(/^[^xyz].*$/.test('xxxxyycc')) // false
console.log(/^[^xyz].*$/.test('acc')) // true
console.log(/^[^xyz].*$/.test('aaxyz')) //  true【字符串是不x/y/z开头的,故也满足】
console.log(/^[^x].*$/.test('1233a')) // true
console.log(/^[^x].*$/.test('xxx')) // false
console.log(/^[^xyz].*$/.test('xxxxyycc')) // false
console.log(/^[^xyz].*$/.test('acc')) // true
console.log(/^[^xyz].*$/.test('aaxyz')) //  true【字符串是不x/y/z开头的,故也满足】

后向引用

断言

js
//js提取 `答案1`和`答案2`
var testString2 = `***** 
我是一个问题
答案1
答案2
*****`;

var res = testString2.match(/(?<=\n我是一个问题)[\s\S]*?(?=\*{5})/g); //返回数组
console.log(res); // [ '\n答案1\n答案2\n' ]
//js提取 `答案1`和`答案2`
var testString2 = `***** 
我是一个问题
答案1
答案2
*****`;

var res = testString2.match(/(?<=\n我是一个问题)[\s\S]*?(?=\*{5})/g); //返回数组
console.log(res); // [ '\n答案1\n答案2\n' ]
js
let reg = /POLYGON\((.*?)\)/gi;

let res = "POLYGON((118.257206432 35.142103492,118.261146368 35.1419743060001,118.261430013 35.1417178180001,118.260999498 35.137444895,118.260715327 35.1372872520001,118.256472888 35.1374869860001,118.257093814 35.1420241000001,118.257206432 35.142103492)),POLYGON((118.261576135 35.1385784340001,118.266236568 35.1384064650001,118.266269116 35.1384018200001,118.266129093 35.1371199160001,118.266007014 35.1370334690001,118.261688791 35.137240954,118.261460704 35.137432776,118.261576135 35.1385784340001))".match(reg) 
console.log(res)
let reg = /POLYGON\((.*?)\)/gi;

let res = "POLYGON((118.257206432 35.142103492,118.261146368 35.1419743060001,118.261430013 35.1417178180001,118.260999498 35.137444895,118.260715327 35.1372872520001,118.256472888 35.1374869860001,118.257093814 35.1420241000001,118.257206432 35.142103492)),POLYGON((118.261576135 35.1385784340001,118.266236568 35.1384064650001,118.266269116 35.1384018200001,118.266129093 35.1371199160001,118.266007014 35.1370334690001,118.261688791 35.137240954,118.261460704 35.137432776,118.261576135 35.1385784340001))".match(reg) 
console.log(res)

关于正则位置匹配(断言)的技巧 - 掘金

  • 零宽度正预测先行断言 (?=exp)
  • 零宽负向先行断言,又称负向向前查找 (?!exp) 似乎相当于 ?=exp 的取反
js
let x1 = `sinM.`.match(/sin(?=M\.)/g); // ["sin"] 
let x2 = `M.sin`.match(/sin(?=M\.)/g); // null
console.log(x1)
console.log(x2)

let x3 = `sinM.`.match(/sin(?!M\.)/g); // ["sin"] 
let x4 = `M.sin`.match(/sin(?!M\.)/g); // null
console.log(x3) // null
console.log(x4) // ["sin"]
let x1 = `sinM.`.match(/sin(?=M\.)/g); // ["sin"] 
let x2 = `M.sin`.match(/sin(?=M\.)/g); // null
console.log(x1)
console.log(x2)

let x3 = `sinM.`.match(/sin(?!M\.)/g); // ["sin"] 
let x4 = `M.sin`.match(/sin(?!M\.)/g); // null
console.log(x3) // null
console.log(x4) // ["sin"]
  • 零宽度正回顾后发断言 (?<=exp) 正向向后查找
  • 零宽负向后行断言,又称负向向后查找 (?<=exp) 负向向后查找
js
let x1 = `sinM.`.match(/(?<=M\.)sin/g); // ["sin"] 
let x2 = `M.sin`.match(/(?<=M\.)sin/g); // null
console.log(x1) // null
console.log(x2) // [ 'sin' ]

let x3 = 'sinM.'.match(/(?<!M\.)sin/g); // ["sin"] 
let x4 = 'M.sin'.match(/(?<!M\.)sin/g); // null
console.log(x3) // [ 'sin' ]
console.log(x4) // null
let x1 = `sinM.`.match(/(?<=M\.)sin/g); // ["sin"] 
let x2 = `M.sin`.match(/(?<=M\.)sin/g); // null
console.log(x1) // null
console.log(x2) // [ 'sin' ]

let x3 = 'sinM.'.match(/(?<!M\.)sin/g); // ["sin"] 
let x4 = 'M.sin'.match(/(?<!M\.)sin/g); // null
console.log(x3) // [ 'sin' ]
console.log(x4) // null

举例

  • \ba\w*\b 匹配单词以a开头+任意数量的数字、字母、下换线,截止到单词结尾
js
console.log('sss '.search(/\ba\w*\b/i)) //  -1
console.log('asss '.search(/\ba\w*\b/i)) //  0
console.log('sss '.search(/\ba\w*\b/i)) //  -1
console.log('asss '.search(/\ba\w*\b/i)) //  0
  • .*? 匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复
    • a.*?b 匹配最短的,以a开始,以b结束的字符串。如果把它应用于aabab的话,它会匹配aab(第一到第三个字符)和ab(第四到第五个字符)
js
console.log('aabab'.match(/a.*?b/g)) // [ 'aab', 'ab' ]
console.log('aabab'.match(/a.*b/g)) // [ 'aabab' ]
console.log('aabab'.match(/a.*?b/g)) // [ 'aab', 'ab' ]
console.log('aabab'.match(/a.*b/g)) // [ 'aabab' ]
  • 贪心匹配/非贪心匹配的举例,例如想将把第二次出现的下划线前的字符串都去掉。例如"ab_cc_mmmm"提取出"mmmm" , "ab_cc_aa_cc"提取出"aa_cc"
originCode.replace(/^(.+?)_(.+?)_/, '');
originCode.replace(/^(.+?)_(.+?)_/, '');