7

正则表达式教程——语法篇

 3 years ago
source link: https://yanhaijing.com/javascript/2017/08/06/regexp-syntax/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

正则表达式,名字听上去就没有吸引力,我发现很多前端对正则表达式都很难做到如数家珍,每次能够运行全凭运气,更有甚者完全靠复制粘贴,其实这样并不好

正则表达式其实并不难,语法就那么多,而且一旦掌握在某些时候能够给解决问题提供捷径,更重要的是面试可能会被问到,要是不会那就尴尬了

本文主要介绍正则表达式的语法部分,下面将正则表达式简称为正则

正则是啥?

同学你可以出门右转了,下面是我自己的理解

正则就是用有限的符号,表达无限的序列,殆已!

正则表达式的语法一般如下(js),两条斜线中间是正则主体,这部分可以有很多字符组成;i部分是修饰符,i的意思表示忽略大小写

/^abc/i

正则定义了很多特殊意义的字符,有名词,量词,谓词等,下面逐一介绍

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

/abc/ // 匹配 abc
/123/ // 匹配 123
/-_-/ // 匹配 -_-
/海镜/ // 匹配 海镜

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

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

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

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

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

\n匹配换行符\r匹配回车符\t匹配制表符,也就是tab键\v匹配垂直制表符\x2020是2位16进制数字,代表对应的字符\u002B002B是4位16进制数字,代表对应的字符\u002B002B是4位16进制数字,代表对应的字符\w匹配任何一个字母或者数字或者下划线\W匹配任何一个字母或者数字或者下划线以外的字符\s匹配空白字符,如空格,tab等\S匹配非空白字符\d匹配数字字符,0~9\D匹配非数字字符\b匹配单词的边界\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},可以匹配aaaaaa

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

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

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

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

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

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

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

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

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

^[]外表示匹配开头的意思

^abc // 可以匹配abc,但是不能匹配aabc

$表示匹配结尾的意思

abc$ // 可以匹配abc,但是不能匹配abcc

上面提到的\b表示单词的边界

abc\b // 可以匹配 abc ,但是不能匹配 abcc

选择表达式

有时我们想匹配x或者y,如果x和y是单个字符,可以使用字符集,[abc]可以匹配abc,如果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'

刻意练习,方能游刃有余,知己知彼,方能百战百胜,正则是前端的一个武器,技多不压身

有时我们会遇到特别复杂的正则,有时候可能不太直观,下面推荐一个图形化展示的工具,我们把涉及到的语法罗列一下

/^[a-z]*[^\d]{1,10}?(aaa|bbb)(?:ccc)$/

可以看到工具能够更快的帮我们理清头绪

505.png

本文仅讲述了语法,下一篇文章将详细介绍如何在js中使用正则,推荐一下glob,号称给人看的正则,比正则的语法简单多了,也是平时开发的神器

原文网址:http://yanhaijing.com/javascript/2017/08/06/regexp-syntax/

微信公众号:颜海镜关注微信公众号 颜海镜微信支付二维码赞赏支持 微信扫一扫

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK