一分钟复习正则

在平时的工做中经常会碰到正则,可是我发现,每次都忘记该怎么去写,因此在这里稍微复习总结一下

先看题

/* 题目一 */
var str1 = '123456765464153513566'
// 分割数字每三个以一个逗号划分(从后往前)
// 如1234 -> 1,234


/* 题目二 */
var str2 = "get-element-by-id"
// 将-的命名方式改成小驼峰
// 指望结果getElementById


/* 题目三 */
var str3 = 'getElementById'
console.log(str3.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase())
// 写出运行结果

看完这三个题目,你是否有想法,下面公布答案git

// 题目一
console.log(str1.replace(/(\d)(?=(\d{3})+$)/g,'$1,'))
// 123,456,765,464,153,513,566

// 题目二
console.log(str2.replace(/-\w/g, ($0) => {
    return $0.slice(1).toUpperCase()
}))
// getElementById

// 题目三
// get-element-by-id

若是你的答案所有正确,那么请忽略下面的内容正则表达式

复习

简单的匹配规则

  • 如想在apple这个单词里找到a这个字符,就直接用/a/这个正则就能够了
  • 若是想匹配*,须要使用\来转义去掉其原本的含义,正则就能够写成/\*/
  • 有一些字符本不是特殊字符,使用转义符号就会让它拥有特殊的含义
特殊字符 正则表达式 记忆方式
换行符 n new line
换页符 f form feed
回车符 r return
空白符 s space
制表符 t tab
垂直制表符 v vertical tab
回退符 [b] backspace,之因此使用[]符号是避免和b重复

匹配多字符

  • 集合的定义方式是使用中括号[],如/[123]/这个正则就能同时匹配1,2,3三个字符。用/[0-9]/就能匹配全部的数字, /[a-z]/则能够匹配全部的英文小写字母
  • 同时匹配多个字符的简便正则表达式:
匹配区间 正则表达式 记忆方式
除了换行符以外的任何字符 . 句号,除了句子结束符
单个数字, [0-9] d digit
除了[0-9] D not digit
包括下划线在内的单个字符,[A-Za-z0-9_] w word
非单字字符 W not word
匹配空白字符,包括空格、制表符、换页符和换行符 s space
匹配非空白字符 S not space

重复匹配

  • 元字符 ? 表明了匹配一个字符或0个字符, 例匹配 colorcolour 这两个单词, 就能够写为 /colou?r/
  • 元字符 * 用来表示匹配0个字符或无数个字符, 例匹配 colorcolouuuuuur 就能够写为 /colou*r/
  • 元字符+适用于要匹配同个字符出现1次或屡次的状况。 colorcolour 这两个单词, 若使用 /colou+r/ 来匹配,就只能匹配到colour
  • 匹配特定的次数, 可使用元字符 {} 用来给重复匹配设置精确的区间范围。如 a 我想匹配3次,那么我就使用 /a{3}/ 这个正则,或者说 a 我想匹配至少两次就是用 /a{2,}/ 这个正则。app

    • {x}: x次
    • {min, max}: 介于min次到max次之间
    • {min, }: 至少min次
    • {0, max}: 至多max次
总结
| 匹配规则 | 元字符 |
| :-----:| :----: |
| 0次或1次 | ? |
| 0次或无数次 | * |
| 1次或无数次 | + |
| 特定次数 | {x}, {min, max} |

位置边界

  • 单词边界 \b , 例 The cat scattered his food all over the room. 匹配出全部的单词cat , 就能够写成 /\bcat\b/g
  • 字符串边界,元字符 ^ 用来匹配字符串的开头。而元字符$ 用来匹配字符串的末尾。

边界总结:post

边界和标志 正则表达式 记忆方式
单词边界 b boundary
非单词边界 B not boundary
字符串开头 ^ -
字符串结尾 $ -
多行模式 m标志 multiple of lines
忽略大小写 i标志 ignore case, case-insensitive
全局模式 g标志 global

子表达式

分组

全部以 () 元字符所包含的正则表达式被分为一组,每个分组都是一个子表达式,它也是构成高级正则表达式的基础。spa

回溯引用

回溯引用(backreference)指的是后面部分引用前面已经匹配到的子字符串。你能够把它想象成是变量,回溯引用的语法像\1 , \2,....,其中 \1 表示引用的第一个子表达式,\2 表示引用的第二个子表达式,以此类推。而 \0 则表示整个表达式。code

// 例如
// 匹配下面字符串中两个连续的单词
// Hello what what is the first thing, and I am am scq000.
var str4 = 'Hello what what is the first thing, and I am am scq000.'

console.log(str4.match(/\b(\w+)\s\1/g))

$1 , $2 ...来引用要被替换的字符串orm

var str = 'abc abc 123';
str.replace(/(ab)c/g,'$1g');
// 获得结果 'abg abg 123'

若是咱们不想子表达式被引用,可使用非捕获正则(?:regex)这样就能够避免浪费内存。ip

var str = 'scq000'.
str.replace(/(scq00)(?:0)/, '$1,$2')
// 返回scq00,$2
// 因为使用了非捕获正则,因此第二个引用没有值,这里直接替换为$2

var str4 = 'scq000 scq001'
console.log(str4.replace(/(scq00)(?:0)/, '$1,$2'))
// 返回 scq00,$2 scq001

前向查找

前向查找(lookahead)是用来限制后缀的。凡是以 (?=regex) 包含的子表达式在匹配过程当中都会用来限制前面的表达式的匹配。例如happy happily这两个单词,我想得到以 happ 开头的副词,那么就可使用/happ(?=ily)/来匹配, 就能够匹配到单词happilyhapp前缀。若是我想过滤全部以 happ 开头的副词,那么也能够采用负前向查找的正则/happ(?!ily)/,就会匹配到happy单词的happ前缀。内存

后向查找

后向查找(lookbehind)是经过指定一个子表达式,而后从符合这个子表达式的位置出发开始查找符合规则的字串。举个简单的例子: applepeople 都包含 ple 这个后缀,那么若是我只想找到 appleple ,该怎么作呢?咱们能够经过限制app这个前缀,就能惟一肯定 ple 这个单词了。element

var str4 = 'apple people';
console.log(str4.replace(/(?<=ap)ple/,'-'))
// 获得结果 'ap- people'
// 说明匹配到的是单词apple的ple

(?<=regex) 的语法就是后向查找regex 指代的子表达式会做为限制项进行匹配,匹配到这个子表达式后,就会继续向后查找。另一种限制匹配是利用(?<!regex) 语法,这里称为负后向查找。与正前向查找不一样的是,被指定的子表达式不能被匹配到。因而,在上面的例子中,若是想要查找 appleple 也能够写成/(?<!peo)ple

总结
| 回溯查找 | 正则 |
| :-----:| :----: |
| 引用 | 0,1,2 和 $0, $1, $2 |
| 非捕获组 | (?:) |
| 前向查找 | (?=) |
| 前向负查找 | (?!) |
| 后向查找 | (?<=) |
| 后向负查找 | (?<!) |

逻辑处理

  • 在正则里面,默认的正则规则都是的关系
  • [] 内部使用的 ^ 表示非的关系
  • 子表达式匹配的非关系就要用到前面介绍的前向负查找子表达式(?!regex)或后向负查找子表达式(?<!regex)
  • 或关系,一般给子表达式进行归类使用。好比,我同时匹配a,b两种状况就可使用(a|b)这样的子表达式。

解析开头的题目

到这里正则差很少已经复习了一遍,咱们如今再去看前面的三道题

题目一

/* 题目一 */
var str1 = '123456765464153513566'
// 分割数字每三个以一个逗号划分(从后往前)
// 如1234 -> 1,234
console.log(str1.replace(/(\d)(?=(\d{3})+$)/g,'$1,'))
// 123,456,765,464,153,513,566

解析:\d表示单个数字,(?=(\d{3})+$)是一个前向查找,\d{3})+$表示匹配3位数字一次或者屡次而且以三位数字结尾。连在一块儿看就是,匹配一个数字,数字后面的数字位数是3的倍数,因此匹配到的数字是3, 6, 5, 4, 3, 3,而后替换为$1,,故3替换为3,6替换为6, ....

题目二

/* 题目二 */
var str2 = "get-element-by-id"
// 将-的命名方式改成小驼峰
// 指望结果getElementById
console.log(str2.replace(/-\w/g, ($0) => {
    return $0.slice(1).toUpperCase()
}))

解析:首先/-\w/g 的意思是匹配全部前面是-单个字符,匹配的结果是-e, -b, -i, 而后取其第二位(也就是将-截取掉),再转换为大写

题目三

/* 题目三 */
var str3 = 'getElementById'
console.log(str3.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase())
// 写出运行结果
// 答案:get-element-by-id

解析: ([a-z])([A-Z])的意思就是匹配两个字母,而且第一个是小写,第二个是大写,因此匹配到的结果是tE, tB, yI,因为()表明分组,故$1表明的是匹配到的小写字母,$2表明的是匹配到的大写字母

参考: 正则表达式不要背
相关文章
相关标签/搜索