参考资料:

匹配规则

正则表达式由字符元字符组成。 字符就是数字和字母组成的,元字符就是特殊的字符,元字符前面需要加”\”,比如想匹配”.”,则需要表示为”.“

一对一的匹配:/a/

比如apple匹配首字母a,就可以用/a/

一对多的匹配:如/0-9/、/a-z/,还可以简写

比如说一个字符只要是数字就满足条件了,那么就可以使用/0-9/
简写形式:

匹配区间 正则表达式 辅助记忆
匹配数字0-9 /\d/ digit
除了数字 /\D/ not digit
匹配包括下划线的单个字符/0-9a-zA-Z_/ /\w/ word
非单字字符 /\W/ not word
匹配空白字符,包括空格制表符等 /\s/ space
非空白字符 /\S/ not space

多对多的匹配:主要分为0|1次,至少0次,至少1次,特定次数

  • 0|1次:使用“?”,比如/colou?r/可匹配color或者colour
  • 至少0次:使用“_”,比如/foo_/可以匹配foo,fooo,…
  • 至少1次:使用“+”。比如/foo+/可以匹配foo,fooo,…
  • 特定次数:使用{},如{3}。{}匹配写法如下:
    • {x}:表示重复x次
    • {min,max}:表示匹配在min到max之间的次数
    • {x,}:表示至少匹配x次
    • {0,max}:表示最多匹配max次

      位置边界

      单词边界

      比如我们想匹配字符串”this cat has many category.”中的”cat”,若使用/cat/会匹配到两个。所以需要单词边界。
      写法为/\bcat\b/,就是在需要匹配的两端加上”\b”

      字符串边界

      若我们想匹配字符串,需要用到”^”和”$”,写法为/^this is a bottle\.$/m。这里注意特殊字符前面需要加”\”,这里的”m”表示使用多行模式。
      总结一下:
边界和标志 正则 解释
单词边界 \b /\bis\b/匹配“this is a cat”中的is,而不是this中的is
非单词边界 \B /\Bis\B/匹配“thishaha is big.”中的thishaha的is
字符串开头 ^ 用于匹配字符串的边界,加上则需匹配一整个字符串
字符串结尾 $ 匹配输入字符串的结尾位置
多行模式 m标志 长文本中若想排除换行符的干扰,就能用上
忽略大小写 i标志
全局模式 g标志 找到所有符合的匹配,若不加g则找第一个符合

特殊字符

特别字符
$ 匹配输入字符串的结尾位置。如果设置了 RegExp 对象的 Multiline 属性,则 $ 也匹配 ‘\n’ 或 ‘\r’。要匹配 $ 字符本身,请使用 \$。
( ) 标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
* 匹配前面的子表达式零次或多次。要匹配 字符,请使用 \
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。
. 匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
[ 标记一个中括号表达式的开始。要匹配 [,请使用 \[。
? 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \?。
\ 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, ‘n’ 匹配字符 ‘n’。’\n’ 匹配换行符。序列 ‘\\‘ 匹配 “\“,而 ‘\(‘ 则匹配 “(“。
^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,当该符号在方括号表达式中使用时,表示不接受该方括号表达式中的字符集合。要匹配 ^ 字符本身,请使用 \^。
{ 标记限定符表达式的开始。要匹配 {,请使用 \{。
| 指明两项之间的一个选择。要匹配 |,请使用 \|。

子表达式

分组与回溯引用

在正则表达式中,使用”()”对表达式进行分组,如“/\b(\w+)\s\1/g”,“\w+”被括号包裹之后,后面的表达式就可以方便引用,即“\1”表示“\w+”,即后面引用前面所匹配的结果。可以使用\1,\2这样的语法来进行回溯引用,\0表示对整个表达式的引用,\1表示对第一个分组的引用。

  1. let str = "Hello what what is the first thing, and I am am scq000."
  2. str.match(/\b(\w+)\s\1/g) // ["what what", "am am"]
  3. str.match(/\b(\w+)\s\w+/g) // ["Hello what", "what is", "the first", ......]

replace中的引用语法有些区别,用$1,$2…来引用要被替换的字符串:

  1. var str = 'abc abc 123';
  2. str.replace(/(ab)c/g,'$1g'); // 'abg abg 123'

如果我们不想子表达式被引用,可以使用非捕获正则(?:regex)这样就可以避免浪费内存。

  1. var str = 'scq000'.
  2. str.replace(/(scq00)(?:0)/, '$1,$2') // 返回scq00,$2

(?:pattern)在使用 “或” 字符 (|) 来组合一个模式的各个部分是很有用:例如,'industr(?:y|ies)' 就是一个比 'industry|industries'更简略的表达式。而且单独存储下 “y” 或者 “ies” 没有什么意义:

  1. a = "British industry"
  2. pattern = "industr(?:y|ies)"
  3. print(re.search(pattern,a).group(0))
  4. // group(1)会报错,因为没有保存捕获到的“y”
  5. pattern = "industr(y|ies)"
  6. print(re.search(pattern,a).group(0, 1))

lookhead

用来匹配前缀,限制后缀的。语法有“(?=regex)”和“(?!regex)”。

  1. let str = "happy happiness"
  2. str.match(/happ(?=iness)/) // ["happ", index: 6, input: "happy happiness", groups: undefined]
  3. str.match(/happ(?!iness)/) // [...index: 0...]

lookbehind

用来匹配后缀,限制前缀。语法有“(?<=regex)”和“(?<!regex)”

  1. let str = "goodness happiness"
  2. str.match(/(?<=happi)ness/)
  3. str.match(/(?<!haha)ness/)

逻辑处理

逻辑关系 正则元字符
|
[^regex] or !

在JS中的正则表达式

两种方法创建

正则表达式在JS中是内置的对象RegExp:

  1. 字面量法: var reg = /\bis\b/g
  2. 构造函数: var reg = new RegExp(‘\bis\b’,’g’)

    涉及到JS的方法:

    str.match(regexp):不加g返回第一个匹配的结果,该结果是一个数组,包含许多项;加g则返回所有匹配字符串的数组,即使匹配一个也是数组形式。
    1. let str = "html,css,javascript";
    2. str.match(/s/) // ["s", index: 6, input: "html,css,javascript", groups: undefined]
    3. str.match(/s/g) // ["s", "s", "s"]
    str.search(regexp|substr):对正则表达式和指定字符串进行匹配搜索,返回第一个出现的匹配项的下标
    str.replace(regexp|substr, newSubStr|function):被用来在正则表达式和字符串直接比较,然后用新的子串来替换被匹配的子串。
    str.split(regexp|substr):全局替换

    使用正则的目的:验证、切分、提取、替换

    验证:查找字符串中是否包含指定的字符串
    1. // 几种判断的方法:
    2. let str = "hello javaScript."
    3. str.indexOf("hello") !== -1; //true
    4. str.includes("hello"); //true
    5. str.search(/hello/) !== -1 //true
    6. !!str.match(/hello/g) // true
    7. /hello/.test(str) // true, RegExp 对象上的方法
    8. !!/hello/.exec(str) // true, RegExp 对象上的方法

    test() 用来查看正则表达式与指定的字符串是否匹配, 返回true或false exec() 方法在一个指定字符串中执行一个搜索匹配, 返回一个结果数组或null

验证总结:

  1. 一个确认的( 精准匹配 )字符查找是否被包含, 使用String.indexOf() 和 String.includes()
  2. 一个有规则的( 模糊匹配 )字符查找是否被包含, 使用RegExp.test() 和 String.search()
  3. 查找不推荐, 使用String.match() 和 RegExp.exec()

切分:将字符串中的字符按照某指定规则进行替换并分成数组

  1. let str = "html,css,javascript";
  2. str.split(/,/) // ["html", "css", "javascript"]

提取:很多时候需要提取部分匹配的数据

  1. // 提取年月日
  2. let str = "2018-10-18";
  3. let regex = /^(\d{4})\D(\d{2})\D(\d{2})$/;
  4. console.log(str.match(regex)); // match, 推荐
  5. regex.exec(str); //exec
  6. let date = [];
  7. str.replace(regex, function(match, year, month, day) { // replace
  8. date.push(year, month, day);
  9. });
  10. console.log(date);

替换:replace就能替换了。