重学js正则表达式(1)

说起正则表达式,相信很多童鞋都和我一样,不愿意花时间去记,用到就度娘。。。一些复杂的表达式即使找到了,也不懂为啥这么用,那我们重学一下吧!o( ̄︶ ̄)o。

定义

正则表达式是一个描述字符模式的对象。js中的正则表达式用RegExp对象表示,用RegExp()构造函数来创建,更多的是用一种特殊的直接量语法来创建。

1
2
3
4
5
// 构造函数定义
let p = new RegExp('a$');

// 直接量
let p = /a$/;

上面2种方式都是用来匹配以a结尾的字符串。
第一个字符是“a”,按字面含义匹配,第二个字符是“$”,具有特殊语义的元字符。
正则表达式的模式规则就是由字符序列组成。

特殊标点符号 ^ $ . * + ? = ! : | \ / ( ) [ ] { }

特殊符号可以具有某种特殊含义,可以当成直接量处理,必须使用前缀\,这是一条通用规则。
例如,”/\ \/“匹配任何包含反斜线的字符串。

字符类

字符类就是将直接量字符放进方括号内匹配它所包含的任意字符,也可以使用连字符表示。
例:

/[abc]/ —————- a,b,c任意一个匹配
/[a-z]/ —————- 匹配拉丁小写字母
/[a-zA-Z0-9]/ ————- 匹配拉丁字母加数字

某些字符类比较常用,因此js正则表达式语法中,使用了这些特殊字符的转义字符来表示。
如下,常用字符类:

  • […] ————— 方括号任意字符
  • [^…] ————– 不在方括号内的任意字符
  • . —————— 除换行和其他Unicode行终止符之外的任意字符
  • \w —————— 等价[a-zA-Z0-9]
  • \W —————— 等价[^a-zA-Z0-9]
  • \s —————— 任意Unicode空白符
  • \S —————— 任意非Unicode空白符,\w \s不同
  • \d —————— 等价[0-9]
  • \D —————— 等价[^0-9]
  • [\b] —————— 退格直接量

重复

用来描述字符重复出现次数的一种正则语法。
/\d\d/ 表示2位数,/\d\d\d\d/表示4位数,但是位数大的话,我们不可能一直写下去,所以才有了表示重复的正则语法。

重复正则语法:

  • {n,m} ——————- 至少n次,不超过m次
  • {n,} ——————- 至少n次或者更多次
  • {n} ——————- 精准n次
  • ? ——————- 0次或1次,等价{0,1}
  • 加号 + ——————- 1次或多次,等价{1,}
  • 星号 * ——————- 任意次,等价{0,}
1
2
3
4
5
6
7
8
9
10
11
// 匹配1~9个数字
/\d{1,9}/

// 精准匹配2个单词和一个可选的数字
\w{2}\d?

// 匹配前后带一个或多个空格的字符串js
/\s+js\s+/

// 匹配任意个非左括号的字符
/[^(]*/

非贪婪的重复

上述列出的匹配重复字符的都是尽可能多的匹配,叫做贪婪匹配。
我们只要在后跟一个问号,就可以变成非贪婪匹配。
例如: ‘aaa’匹配字符串, /a+/ 会匹配3个a,/a+?/ 之会匹配1个a。

选择、分组和引用

  • 字符 “|”,用于分隔供选择的字符。
    例如: /java|python/ 可以匹配“java”,也可以“python”

注意:

选择项的尝试匹配顺序是从左往右,直到发现匹配项
例如:/a|ab/ 匹配字符串“ab”时,只能匹配“a”

  • 圆括号( )
    1)把单独的项组合成子表达式。
    例如:/java(Script)?/ 匹配字符串“java”,也可以是“JavaScript”

    2)在完整的模式中定义子模式。
    当正则表达式成功的和目标字符串匹配时,可以从目标串中抽出和圆括号中的子模式相匹配的部分。
    例如:/a-z+\d+/ 匹配任意个小写字母后面跟任意个数字,假设我们只关心字母后面的数字的话,可以使用/a-z+(\d+)/ ,就可以成功抽取数字。

    3)允许同一正则表达式的后部引用前面的子表达式,指的是与那个模式相匹配的文本的引用(通过\1,“\”后面加数字实现,\1引用的是第一个圆括号的子表达式)
    例如:

    1
    2
    3
    4
    5
    // 匹配位于单引号或双引号内的任意个字符,但是没有要求左侧和右侧的引号匹配。
    /['"][^'"]*['"]/

    // 匹配的左侧和右侧引号相同。
    /(['"])[^'"]*\1/

指定位置

像\b 这样不匹配可见字符,制定匹配位置的元素,称为正则表达式的锚。

  • ^ ———— 匹配字符串的开头
  • $ ———— 匹配字符串的结尾
1
2
3
/^java/   匹配以“java”开头
/java$/ 匹配以“java”结尾
/^java$/ 准确匹配“java”字符
  • \b 匹配单词的边界,位于\w 和 \W之间的位置,或位于\w 和开头或结尾之间的位置。
  • \B 匹配非单词的边界。

    1
    2
    /\sjava\s/  匹配前后都有空格的“java”,但是匹配不到开头和结尾,匹配到的前后都有空格
    /\bjava\b/ 这样就可以匹配任何位置的字符“java”
  • (?= ) 先行断言,括号内的表达式必须正确匹配。

  • (?!) 负先行断言,括号内的表达式都不必匹配。
    1
    2
    3
    /[Jj]ava(?=\:/  匹配“java:is good”中的“java”,但是不能匹配“java is good”中的“java”,必须带冒号。
    /Java(?!Script)([A-Z]\w*)/ 匹配“Java”后跟随一个大写字母和任意多个单词 ,但是不能跟“Script”。
    匹配“JavaBeans”,不能匹配“Javabeans”。

修饰符

修饰符是放在“/” 符号之外,而且是第二条斜线后。

  • i —————- 执行不区分大小写的匹配。
  • g —————- 全局匹配,找到所有的匹配,不是第一个找到就停止。
  • m —————- 多行匹配模式,^匹配一行的开头和字符串的开头,$匹配行的结束和字符串的结束。

本小节主要介绍了创建正则表达式的语法,并未尝试在js中使用,下一节,我们开始讨论String对象用以执行正则表达式模式匹配和检索替换的方法,RegExp对象的方法及属性。