aermin/blog

正则总结

aermin opened this issue · 0 comments

正则表达式

使用下面类似 Perl 的语法,就可以创建一个正 则表达式。

var expression = / pattern / flags ;

其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、 向前查找以及反向引用。每个正则表达式都可带有一或多个标志(flags),用以标明正则表达式的行为。 正则表达式的匹配模式支持下列 3 个标志。

  • g:表示全局(global)模式,即模式将被应用于所有字符串,而非在发现第一个匹配项时立即 停止;
  • i:表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略模式与字符串的大小写;
  • m:表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在与模 式匹配的项。
var text = "aaa "; 
var pattern1 = /\s$/; //匹配字符串末尾的空格 
pattern1.exec(text);

正则定义了很多特殊意义的字符,有名词,量词,谓词等

简单字符

没有特殊意义的字符都是简单字符,简单字符就代表自身,绝大部分字符都是简单字符,举个例子

/abc/ // 匹配 abc
/123/ // 匹配 123
/-_-/ // 匹配 -_-

转义字符

\是转义字符,其后面的字符会代表不同的意思,转义字符主要有三个作用:

第一种,是为了匹配不方便显示的特殊字符,比如换行,tab符号等

第二种,正则中预先定义了一些代表特殊意义的字符,比如\w等

第三种,在正则中某些字符有特殊含义(比如下面说到的),转义字符可以让其显示自身的含义

下面是常用转义字符列表:

常用转义字符 意义
\n 匹配换行符 (newline)
\r 匹配回车符 (return)
\t 匹配制表符,也就是tab键
\v 匹配垂直制表符
\x20 20是2位16进制数字,代表对应的字符
\u002B 002B是4位16进制数字,代表对应的字符
\u002B 002B是4位16进制数字,代表对应的字符
\w 匹配任何一个字母或者数字或者下划线 单子字符 (word)
\W 匹配任何一个字母或者数字或者下划线以外的字符 非单子字符
\s 匹配空白字符,如空格,tab等 (space)
\S 匹配非空白字符
\d 匹配数字字符,0~9 (digit)
\D 匹配非数字字符
\b 匹配单词的边界 (boundary)
\B 匹配非单词边界
\ 匹配\本身

字符集合

有时我们需要匹配一类字符,字符集可以实现这个功能,字符集的语法用[]分隔,下面的代码能够匹配a或b或c

[abc]

如果要表示字符很多,可以使用-表示一个范围内的字符,下面两个功能相同

[0123456789]

[0-9]

在[]内的开头添加^,可表示非的意思,下面的代码能够匹配abc之外的任意字符

[^abc]

其实正则还内置了一些字符集,在上面的转义字符有提到,下面给出内置字符集对应的自定义字符集

匹配除了换行符(\n)以外的任意一个字符 = [^\n]
\w = [0-9a-zA-Z_]
\W = [^0-9a-zA-Z_]
\s = [ \t\n\v]
\S = [^ \t\n\v]
\d = [0-9]
\D = [^0-9]

量词

如果我们有三个苹果,我们可以说自己有个3个苹果,也可以说有一个苹果,一个苹果,一个苹果,每种语言都有量词的概念

如果需要匹配多次某个字符,正则也提供了量词的功能,正则中的量词有多个,如?、+、*、{n}、{m,n}、{m,}

{n}匹配n次,比如a{2},匹配aa

{m, n}匹配m-n次,优先匹配n次,比如a{1,3},可以匹配aaa、aa、a

{m,}匹配m-∞次,优先匹配∞次,比如a{1,},可以匹配aaaa...

?匹配0次或1次,优先匹配1次,相当于{0,1}

+匹配1-n次,优先匹配n次,相当于{1,}

*匹配0-n次,优先匹配n次,相当于{0,}

正则默认和人心一样是贪婪的,也就是常说的贪婪模式,凡是表示范围的量词,都优先匹配上限而不是下限

a{1, 3} // 匹配字符串'aaa'的话,会匹配aaa而不是a

var text = "aaa"; 
var pattern1 = /a{1,3}/;
pattern1.exec(text); //["aaa", index: 0, input: "aaa"]

有时候这不是我们想要的结果,可以在量词后面加上?,就可以开启非贪婪模式

var text = "aaa"; 
var pattern1 = /a{1,3}?/;
pattern1.exec(text);//["a", index: 0, input: "aaa"]

字符边界

有时我们会有边界的匹配要求,比如以xxx开头,以xxx结尾

^在[]外表示匹配开头的意思
^abc // 可以匹配abc,但是不能匹配aabc

$表示匹配结尾的意思
abc$ // 可以匹配abc,但是不能匹配abcc
上面提到的\b表示单词的边界

\b表示匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者没有其他“字”字符在其前面的位置。
abc\b // 可以匹配 abc ,但是不能匹配 abcc;
/\bm/匹配“moon”中得‘m’;
/oo\b/并不匹配"moon"中得'oo',因为'oo'被一个“字”字符'n'紧跟着。
/oon\b/匹配"moon"中得'oon',因为'oon'是这个字符串的结束部分。这样他没有被一个“字”字符紧跟着。
/\w\b\w/将不能匹配任何字符串,因为在一个单词中间的字符永远也不可能同时满足没有“字”字符跟随和有“字”字符跟随两种情况。

选择表达式

有时我们想匹配x或者y,如果x和y是单个字符,可以使用字符集,[abc]可以匹配a或b或c,如果x和y是多个字符,字符集就无能为力了,此时就要用到分组

正则中用|来表示分组,a|b表示匹配a或者b的意思

123|456|789 // 匹配 123 或 456 或 789

分组与引用

分组是正则中非常强大的一个功能,可以让上面提到的量词作用于一组字符,而非单个字符,分组的语法是圆括号包裹(xxx)

(abc){2} // 匹配abcabc

分组不能放在[]中,分组中还可以使用选择表达式

(123|456){2} // 匹配 123123、456456、123456、456123

和分组相关的概念还有一个捕获分组和非捕获分组,分组默认都是捕获的,在分组的(后面添加?:可以让分组变为非捕获分组,非捕获分组可以提高性能和简化逻辑

'123'.match(/(?:123)/) // 返回 ['123']
'123'.match(/(123)/)  // 返回 ['123', '123']
和分组相关的另一个概念是引用,比如在匹配html标签时,通常希望<xxx></xxx>后面的xxx能够和前面保持一致

引用的语法是\数字,数字代表引用前面第几个捕获分组,注意非捕获分组不能被引用

<([a-z]+)><\/\1> // 可以匹配 `<span></span>` 或 `<div></div>`等

预搜索

如果你想匹配xxx前不能是yyy,或者xxx后不能是yyy,那就要用到预搜索

js只支持正向预搜索,也就是xxx后面必须是yyy,或者xxx后面不能是yyy

1(?=2) // 可以匹配12,不能匹配22
1(?!2) // 可有匹配22,不能匹配12

修饰符

默认正则是区分大小写,这可能并不是我们想要的,正则提供了修饰符的功能,修复的语法如下

/xxx/gi // 最后面的g和i就是两个修饰符

g正则遇到第一个匹配的字符就会结束,加上全局修复符,可以让其匹配到结束

i正则默认是区分大小写的,i可以忽略大小写

m正则默认情况下,^和$只能匹配字符串的开始和结尾,m修饰符可以让^和$匹配行首和行尾,不理解就看例子

/jing$/ // 能够匹配 'yanhaijing,不能匹配 'yanhaijing\n'
/jing$/m // 能够匹配 'yanhaijing, 能够匹配 'yanhaijing\n'

/^jing/ // 能够匹配 'jing',不能匹配 '\njing'
/^jing/m // 能够匹配 'jing',能够匹配 '\njing'

js使用正则表达式的方法

正则表达式是用于匹配字符串中字符组合的模式。在 JavaScript中,正则表达式也是对象。这些模式被用于 RegExp 的 exec 和 test 方法, 以及 String 的 match、replace、search 和 split 方法

方法 描述
exec 一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回null)。
test 一个在字符串中测试是否匹配的RegExp方法,它返回true或false。
match 一个在字符串中执行查找匹配的String方法,它返回一个数组或者在未匹配到时返回null。
search 一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
replace 一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
split 一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的String方法。

当你想要知道在一个字符串中的一个匹配是否被找到,你可以使用test或search方法;想得到更多的信息(但是比较慢)则可以使用exec或match方法。如果你使用exec或match方法并且匹配成功了,那么这些方法将返回一个数组并且更新相关的正则表达式对象的属性和预定义的正则表达式对象(详见下)。如果匹配失败,那么exec方法返回null(也就是false)。

var text = "cat, bat, sat, fat"; var pattern1 = /.at/;

var matches = pattern1.exec(text);
console.log(matches) //["cat", index: 0, input: "cat, bat, sat, fat"]

正则里面带变量

可用ES6模板语法,注意\要多写一次,不然会被new RegExp 过滤掉

const regexp = new RegExp(`@${this._userInfo.name}\\s\\S*|@${this._userInfo.name}$`);

参考鸣谢:
正则表达式教程——语法篇和mdn的正则表达式

正则匹配