正则表达式

270 阅读3分钟

正则表达式

基础知识请参考别的文章,比如MDN-js正则表达式。本文只会罗列一些不太确定的情况。

字符串和正则表达式之间的关系。

注意点

  • ^

这个小可爱在[]外面表示首位的意思,比如/^h/匹配到以h开头的h。

在[]中放在首位则表示非,比如/[^abc]/匹配不是abc中任意一个的字符

^在字符集[]是取反的意思,并且只有放在首位的时候才表示非,放在其他位置表示^字符本身

  • []

. *这种特殊字符在 []字符集中不再特殊哦,比如/^[a{3}]$/匹配不了'aaa',记住只代表1个字符(\t算是1个字符)哦!/^[a{3}]$/可以匹配'a','{',3,'3','}'

Character set. This pattern type matches any one of the characters in the brackets, including escape sequences. Special characters like the dot(.) and asterisk (*) are not special inside a character set, so they don't need to be escaped. You can specify a range of characters by using a hyphen, as the following examples illustrate. The pattern [a-d], which performs the same match as [abcd], matches the 'b' in "brisket" and the 'c' in "city". The patterns /[a-z.]+/ and /[\w.]+/ match the entire string "test.i.ng".

[9-1]会怎样?

var reg = /[9-0]/;

result: VM100:1 Uncaught SyntaxError: Invalid regular expression: /[9-0]/: Range out of order in character class
    at <anonymous>:1:11

  • ()

(p) 捕获 + 将p看作一个整体

(?:p) 不捕获 + 将p看作一个整体(?:p1|p2|p3)也可以。

(?=p) p前面的位置(正向先行断言lookahead)

(?!p)不是p的前面的位置(负向先行断言negated lookahead)

(?<=y)x 匹配前面是y的x

(?<!y)x 匹配前面不是y的x

分组捕获
var re = /(\w+)\s(\w+)/;
var str = 'John Smith';
var newstr = str.replace(re, '$2, $1');
console.log(newstr);
// "Smith, John"

var re = /(bar){2,3}/;
var str = 'barbarbar hellobar nobar wantabar';
str.match(re);
// ["barbarbar", "bar", index: 0, input: "barbarbar hellobar nobar wantabar", groups: undefined]
如果不想捕获但是仍然想将bar作为一个子表达式进行2~3个匹配

var re = /(?:bar){2,3}/;
var str = 'barbarbar hellobar nobar wantabar';
str.match(re);

\w 是字符组 [0-9a-zA-Z_] 的简写形式,即 \w 是字母数字或者下划线的中任何一个字符

\b具体就是 \w 与 \W 之间的位置,也包括 \w 与 ^ 之间的位置,和 \w 与 $ 之间的位置

匹配前面一个表达式0次或者1次。等价于 {0,1}。

出现在*, +, ?, {}后面,表示开启非贪婪模式(默认是贪婪模式)

/ab?$/.test('a'); // true
/ab?$/.test('ab'); // true

'abbbbbc'.match(/ab+?/); 
// ["ab", index: 0, input: "abbbbbc", groups: undefined]

'abbbbbc'.match(/ab+/); 
// ["abbbbb", index: 0, input: "abbbbbc", groups: undefined]

js中和正则表达式相关的函数

RegExp

test

regex.test(s) 在s中是否能搜索到满足regex的内容,返回true或false。

var regex = /abc/; 
var s = '123abc';
regex.test(s); // true

var regex = /abc/g;
var s = '123abc';
var s2 = 'abc';
regex.test(s); // true
regex.test(s); // false

regex.test(s); // true
regex.test(s2); // false 

s.search(regex)结果为-1,表示没有搜到,则regex.test(s)为true。如果是其他index值,表示搜索到且位置在index,则regex.test(s)为false。

如果regex是全局正则表达式,继续调用regex.test(),即使对象是不同的字符串,它还是会从新的字符串的regex.lastIndex位置开始搜索,不过你可以修改regex.lastIndex的值,或者当regext.test()返回false后,regex.lastIndex恢复为0.

exec

regex.exec(s) exec() 方法在字符串s中执行一个搜索匹配。返回一个结果数组或 null。

MDN-exec

如果regex不是全局正则表达式,regex.lastIndex永远是0,否则,每次执行完regex.exec(s)会更新regex.lastIndex为匹配到的字符串末位的下一位(继续搜索)。

返回的数组中还有分组捕获信息哦!

该方法经常用在while中用来找到一段文字中所有匹配项,但是要小心,不要忘记两点:1、/xx/g一定是全局正则表达式 2、正则表达式不能在while中定义(while(/ab/g.exec('abc')) {})以上两种情况都可能陷入死循环。

String

以下方法的参数都是正则表达式,如果不是正则表达式,则会new RegExp(xx)完成转换。

match

s.match(regex)

返回结果

  • regex不使用g标志,返回数组。(返回结果和RegExp.exec(s)相同)
[第一个匹配结果, 分组捕获$1, 分组捕获$2..., index, input, groups]

分组捕获结果:有几个就列出来几个。

index:搜索到匹配的位置。 

input: 就是s,字符串的内容。

groups: 分组捕获如果有名字就显示名字,没有就显示undefined。

命名捕获分组的语法是 (?<name>...)
反向引用一个命名分组的语法是 \k<name>
在 replace() 方法的替换字符串中反向引用是用 $<name>

let str = "test1test2";
str.match(/(\w)(\w)(?<number>\d)/)
["st1", "s", "t", "1", index: 2, input: "test1test2", groups: {
    "number": 1
}]

分组提案参考

  • regex使用g标志,返回数组,数组元素为匹配到的每一项结果。(分组捕获就会忽略掉哦!)
  • 没有匹配,返回null

split

不会改变字符串本身。

str.split(string|regex, limit) 当参数为正则表达式时,regex是不是全局正则表达式无所谓啦。

如果正则表达式包含至少一个捕获组,那么它将会返回一个数组,其中结果会跟捕获组互相交替。

limit: 数组元素的个数(Math.min(limit, 实际拆分后的个数))。包括分组捕获的元素。

'1ab23a5c'.split(/(\d)(\w)/); 
// ["", "1", "a", "b", "2", "3", "a", "5", "c", ""]

'1ab23a5c'.split(/(\d)(\w)/, 5);
// ["", "1", "a", "b", "2"]

'abc'.split()
// ["abc"]

'abc'.split('abc')
// ["", ""]

''.split('')
// []

''.split()
// [""]

replace

不会改变字符串本身。

str.replcace(string|regex, string | function)是不会改变str本身的哦

返回值是一个新的字符串。

regex有g标志,则替换所有匹配项,否则只替换第一个。

$1$2...代表捕获的内容
$`插入匹配左边的内容
$'插入匹配右边的内容
?插入$

第二个参数如果是函数,函数的参数要记住。如果regex有g,每次匹配函数都会被执行。参数参考

search

s.search(regex) 在字符串s中搜索满足regex规则的内容,如果搜到返回第一个匹配的位置,如果没搜到返回-1。

regex是不是全局正则表达式无所谓啦。

matchAll

s.matchAll(regex)

目前处于Stage 3(Canidate)阶段。

matchAll()跟批量调用exec()的工作很像,即可以获取分组捕获又不用循环,多棒!

注意点是返回的是一个迭代器,可以通过解构赋值方便使用。

regex是不是全局正则表达式无所谓啦。

唯手熟尔。