正则表达式修饰符、运算符、元字符、分组、方法和字符串相关正则方法

679 阅读5分钟

正则表达式

学习写正则表达式可以配合图解正则表达式网址使用。可以更好的理解正则表达式的含义

图解正则表达式:点击跳转

修饰符

标记也称为修饰符,正则表达式的标记用于指定额外的匹配策略。

标记不写在正则表达式里,标记位于表达式之外,格式如下:

字符含义
iignore - 不区分大小写 将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。
gglobal - 全局匹配 查找所有的匹配项。
mmulti line - 多行匹配 使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。
s特殊字符圆点 . 中包含换行符 \n 默认情况下的圆点 . 是 匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。
'BAnANa'.replace(/a+/g,'*') // "BAnAN*"
'BAnANa'.replace(/a+/gi,'*') // "B*n*N*"

运算符

\的含义

字符含义
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。
// 示例1
'1wa2b3e'.replace(/w/,'*') // "1*wa2b3e"
// 示例2
'1wa2b3e'.replace(/\w/,'*') // "*wa2b3"

^和$的含义

字符含义
^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '\n' 或 '\r' 之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '\n' 或 '\r' 之前的位置。
/^a/.test('a2sfade3') // true
/^a/.test('234weras') // false
/a$/.test('12sfadea') // true
/a$/.test('12sfadew') // false

第一个字符串以a开头,匹配结果为true,第二个字符串非a开头,匹配结果为false。
第三个字符串以a结尾,匹配结果为true,第四个字符串非a结尾,匹配结果为false

如上面两个示例所示,示例一中的正则未加转义符\,匹配的是原义字符w。第二个示例\w(后面会讲到)则是匹配字符串中出现的第一个字母、数字、或下划线。

或关系

字符含义
x|y匹配 x 或 y。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
'aabbcacaabc'.replace(/[a|b]/,'*') // "*abbcacaabc"
'aabbcacaabc'.replace(/[a|b]/g,'*') // "****c*c***c"
// LiLei替换成李雷;
'My name is Lilei'.replace(/Li(L|l)ei/g,"李雷");

?、*、+等限制出现次数的限定符的含义

字符含义
匹配前面的子表达式零次或一次。 等价于 {0,1}。
*匹配前面的子表达式零次或多次。 等价于{0,}。
+匹配前面的子表达式一次或多次。例如。 等价于 {1,}。
{n}n 是一个非负整数。匹配确定的 n 次。
{n,}n 是一个非负整数。至少匹配n 次。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。
?当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
'aabbbaaaab'.replace(/a{3}/,'*') // "aabbb*ab"
'aabbbaaaab'.replace(/a{3,}/,'*') // "aabbb*b"
'aabbbaaaab'.replace(/a{2,3}/g,'*') // "*bbb*ab"

元字符

正则表达式基本由两种字符串类型组成:原文文本字符和元字符。元字符就是指那些在正则表达式中具有特殊意义的专用字符。

下面我们一起来看看元字符有哪些。

常用转义符加字母的元字符含义

字符含义
\d匹配一个数字字符。等价于 [0-9]。
\D匹配一个非数字字符。等价于 [^0-9]。
\w匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'。
\W匹配非字母、数字、下划线。等价于 '[^A-Za-z0-9_]'。
/\d/.test('a') // false
/\d/.test('1') // true
/\D/.test('a') // true
/\D/.test('1') // false
/\w/.test('a_1') // true
/\w/.test('%') // false
/\W/.test('a_1') // false
/\W/.test('%') // true

边界元字符

字符含义
\b匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
(pattern)匹配 pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 00…9 属性。要匹配圆括号字符,请使用 '(' 或 ')'。
(?:pattern)匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 () 来组合一个模式的各个部分是很有用。例如, 'industr(?:yies) 就是一个比 'industryindustries' 更简略的表达式。
(?=pattern)正向肯定预查(look ahead positive assert),在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,"Windows(?=9598NT2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)正向否定预查(negative assert),在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如"Windows(?!9598NT2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?<=pattern)反向(look behind)肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=9598NT2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。
(?<!pattern)反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!9598NT2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。
// 边界符:\b  范围为:\W范围
 "is this a book?".match(/\bis\b/g); // ["is"]
// 正向肯定预查;
let str = "iphone3iphone4iphone11iphoneNumber";
// iphone 换成“苹果”;
let reg = /iphone(?=\d{1,2})/g;
let res = str.replace(reg,"苹果");
console.log(res);
// 正向否定预查;
let str = "iphone3iphone4iphone11iphoneNumber";
// iphone 换成“苹果”;
let reg = /iphone(?!\d{1,2})/g;
let res = str.replace(reg,"苹果");
console.log(res);
// 负向肯定预查;
let str = "10px20px30pxipx";
// px-->像素;
let reg =  /(?<=\d{2})px/g;
let res = str.replace(reg,"像素");
console.log(res);
// 负向否定预查;
let str = "10px20px30pxipx";
// px-->像素;
let reg =  /(?<!\d{2})px/g;
let res = str.replace(reg,"像素");
console.log(res);

制表符等常用元字符

字符含义
\f匹配一个换页符。等价于 \x0c 和 \cL。
\n匹配一个换行符。等价于 \x0a 和 \cJ。
\r匹配一个回车符。等价于 \x0d 和 \cM。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t匹配一个制表符。等价于 \x09 和 \cI。
\v匹配一个垂直制表符。等价于 \x0b 和 \cK。
/\f/.test('\x0c') // true

字符集合

字符含义
[xyz]字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz]负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'、'l'、'i'、'n'
[a-z]字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z]负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
'plain'.replace(/[abc]/g,'*') // "pl*in"
'plain'.replace(/[^abc]/g,'*') // "**a**"
/[a-z]/.test('aglkshjeroihskjngbhlskfgh') // true
/^[a-z]/.test('aglkshjeroihskjngbhlskfgh') //false

其他元字符

字符含义
\cx匹配由 x 指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符
\xn匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,'\x41' 匹配 "A"。'\x041' 则等价于 '\x04' & "1"。正则表达式中可以使用 ASCII 编码。
\num匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)\1' 匹配两个连续的相同字符。
\n标识一个八进制转义值或一个向后引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为向后引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm标识一个八进制转义值或一个向后引用。如果 \nm 之前至少有 nm 个获得子表达式,则 nm 为向后引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的向后引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, \u00A9 匹配版权符号 (?)。

分组

什么是分组

对于要重复单个字符,非常简单,直接在字符后卖弄加上限定符即可,例如 a+ 表示匹配1个或一个以上的a,a?表示匹配0个或1个a。但是我们如果要对多个字符进行重复怎么办呢?此时我们就要用到分组,我们可以使用小括号()来指定要重复的子表达式,然后对这个子表达式进行重复,例如:(abc)? 表示0个或1个abc 这里一 个括号的表达式就表示一个分组 。

'abcdababcdababcdabacdbab'.replace(/(ab){2}/g,"*"); // "abcd*cd*cdabacdbab"

分组可以分为两种形式,捕获组和非捕获组。
在表达式(A)(B(C)) 中,存在四个这样的组: | 下标 | 组 | | ---- | ------------------------------------ | |0 | (A)(B(C)) | | 1| (A) | |2| (B(C)) | |3 | (C) |

// 转换时间格式:2020-12-09 ---->  2020/12/09
 "2020-12-09".replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g,"$1/$2/$3"); // "2020/12/09"

反向引用

// 转换时间格式:2020-12-09  ---->  09/12/2020;
 "2020-12-09".replace(/(\d{4})-(\d{1,2})-(\d{1,2})/g,"$3/$2/$1"); // "09/12/2020"

命名分组

// ?<分组名>  ES2018新增特性;
let res = "$name=zhangsan&age=20".match(/\$(?<str>\w+)/);
console.log(res.groups.str); // "name"

正则方法

test

test()方法搜索字符串指定的值,根据结果并返回真或假。

/abc/.test('abc') // true
/abd/.test('abc') // false

exec

exec() 方法检索字符串中的指定值。返回值是被找到的值。如果没有发现匹配,则返回 null

/abc/.exec('qabcz') // ["abc", index: 1, input: "qabcz", groups: undefined]
/abd/.exec('qwerr') // null

字符串相关正则方法

replace

replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

适用于替换敏感词汇

"购买一台苹果手机".replace(/苹果/,'*') // "购买一台*手机"
"购买一台苹果手机".replace(/苹果/,function(v){
return '*'.repeat(v.length)
})// "购买一台**手机"

match

match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。

"fdsa1231dfaf232fda".match(/\d+/g) // ["1231", "232"]

search

search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。

"fdsa1231dfaf232fda".search(/\d+/g) // 4