面试官:这么简单的正则表达式都不会?

1,304 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

正则表达式有多神奇

最近发现很多的面试和笔试中都经常出现正则表达式相关的题目,面试官:这么简单的正则表达式都不会?面试者:嘴角微微上扬,回以一个不失礼而尴尬的笑

熟练掌握正则表达式,不仅能够在面试中体现编程水平,在平时的开发过程中也能够用于优化我们的代码,让我们写出更加精炼的语句, 这不就是老鸟装ABCDEFG之道吗, 在CodeReview的时候假装不经意间写出一条老长老长的正则表达式,丢到新鸟面前,云淡风轻得说一句,这不就简简单单一条正则就能解决吗,写这么多代码干嘛?

回到正题,最近这段时间重新学了下正则表达式,还是发现正则表达式有很多值得学习的地方,今天我就通过这篇文章记录一下自己学习正则表达式的笔记,也希望能够分享给大家,一起快乐搬砖!

正则表达式 VS 循环+判断

先来举个例子,题目是这样子

    给出两个字符串 str 和 sub,你的任务是在 str 中完全删除那些在 sub 中存在的字符。
    注:字符串包含空格,1len(str),len(sub)≤10^5

    输入:  
    str="I am YimWu",sub="abc"
    输出: 
    "I m YimWu"

循环+判断

我们来看一下,作为不知道正则表达式的小白,我们该怎么处理呢?万物皆可循环,这个时候我们祭出祖传“循环+判断”王炸组合

let CharacterDeletion = (str, sub) => {
  // 剔除字符串中所有的目标字符
  let replaceFun = (replaceStr,char) => {
    // 用于保存剔除操作后的字符串
    let r = replaceStr
    // 若没有找到对应字符则返回原字符串
    if(r.indexOf(char) == -1){
      return r
    }else{
      // replace匹配到第一个字符并剔除
      r = r.replace(char,'')

      // 剔除后再次检查是否还有需要剔除的字符
      // 无则返回,有则递归调用原函数
      if(r.indexOf(char) == -1){
        return r
      }else{
        return replaceFun(r, char)
      }
    }
  }
  let r = str
  sub.split('').forEach(ele => {
    r = replaceFun(r, ele)
  });
  return r
}

// 输出返回
console.log(
  CharacterDeletion('I am YimWu', 'aeiou') // result => I m YmW
)

到这里总算憋屈地把结果写出来了,虽然代码量不算很多,但是由于 node 环境中不支持replaceAll (Version>85的chrome支持),所以只能用递归来完成replaceAll的功能,所以代码的可读性随即降低了很多,这里可能还有其他的解法,就不一一展示了,有兴趣的小伙伴可以留言区交流交流

正则表达式

说完了上面憋屈的解法,我们来看看使用正则表达式的写法

// 字符串过滤
let CharacterDeletion = (str, sub) => {
  // 利用eval动态拼接正则表达式
  let reg = eval(`/[${sub}]/g`)
  return str.replace(reg, '')
}

// 输出返回
console.log(
  CharacterDeletion('I am YimWu', 'aeiou') // result => I m YmW
)

OhMyGod!!!快,块扶我起来,我想学习!!

显而易见,对于第一种方法需要十几二十行代码才能解决的问题,利用正则表达式5行就可以直接解决,不仅代码量大大减少了,而且代码的可读性也提高了不少,所以还不快来跟我学一学这欲罢不能的正则表达式

正则表达式有哪些用法

正则表达式的用法有很多,但是平常我们工作中,面试中用到的大部分都是正则表达式的基础用法,所以今天主要以介绍基础的用法为主,如果需要更加系统,深入的学习正则表达式,可以阅读文末参考书籍、文章进行学习

正则的匹配方式

按生活经验来说,我们都知道,如何事情,都有相对的两面,那么,正则表达式其实也一样,正则表达式也有两种相反的匹配方式,举两个实际应用的例子:

正向匹配——匹配与表达式相符的内容

我们在用 webpack 打包时需要让 webpack 知道,什么文件用什么 loader 进行解析,那么我们需要在 webpack 的 module.rules 中写入匹配的正则表达式,匹配特定的文件后缀名,如 /\.vue/,这个表达式的作用是,匹配所有以 .vue 结尾的文件,这就是正向匹配

反向匹配——匹配与表达式不相符的内容

我们都知道前端安全问题主要集中在登录框、留言框以及各种接受输入的位置,那么作为前端,我们该如何防范呢,其中有一个比较有效的便是正则表达式的反向匹配。
前端最常见的攻击有两种,一种是xss攻击,另一种是注入攻击,两种攻击最基础的防范方式就是利用正则表达式,排除特殊字符(如<>|等),达到屏蔽部分攻击的可能
例如:

/[^%--`~!@#$^&*()=|{}':;',\[\]\.<>]/

这就是摘抄了某系统的过滤语句(不一定严谨),该语句匹配不符合的,才是前端允许输入的内容

正则表达式相关方法

const str = 'abc'
// test 验证是否满足正则表达式,返回 true/false
str.test(/[a-z]/)
// match 返回正则表达式匹配结果 返回数组
str.match(/[a-z]/)

正则表达式匹配字符

元字符

字符含义
\d[0-9]/表示0-9其中一位
\D[^0-9]/表示除了0-9之外的任意字符
\w[0-9a-zA-Z_]/表示数字、字母以及下划线
\W[^0-9a-zA-Z_]/表示非单词、字母以及下划线
\s[\t\v\n\r\f]/表示各种空白符号,空格、制表符等
\S[^\t\v\n\r\f]/表示非空白字符
.[^\n\r\u2028\u2029]/表示除了换行符、回车符、行分隔符和段分隔符之外的字符

数量以及范围字符

字符含义
+{1, }/表示至少需要出现一次
*{0, }/表示出现任何次,包含不出现
?{0,1}/表示不出现或者出现一次
{m, }至少出现 m 次

其他字符

字符含义
|表示分支,/a | b/, 表示a或b
在开头表示匹配以某字符开头,在字符集中表示反向匹配
$在末尾表示匹配以某字符结尾
|表示分支,/a | b/, 表示a或b
/RegExp/ ii 即 ignore,表示匹配时忽略大小写
/RegExp/ gg 即 global,表示全文匹配

正则表达式实践例子

上面列了几个表格,把基本用法都罗列了一遍,理论已经到位,那么接下来就举一些我平时工作中具体的例子,看看如何利用这些字符,通过排列组合,实现灵活多变的需求吧!

匹配信息中的手机号码

// \d 表示匹配数字,{11}表示匹配11位
const str = 'yimwu: 19448751214'
str.match(/\d{11}/)

webpack loader 配置中,匹配所有的vue文件

// \. 表示转义,vue$ 表示以 vue 结尾,即 vue 相关的源文件
const fileName = 'app.vue'
const reg = /\.vue$/
reg.test(filename)

只允许上传 png 和 jpg 格式的图片

const reg = /(\.png$)|(\.jpg$)/
const uploadFileName = 'pic.png'
reg.test(uploadFileName)

匹配十六进制颜色

// 颜色由 #开头,加上3、6位16进制数组成
const reg = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/
reg.test('#c8c8c8') // true

匹配日期

// {4}量词前表示匹配年份
// (0[1-9]|1[0-2]) 匹配的是月份 01-12
// (0[1-9]|[12][0-9]|3[01]) 这里需要特别注意的是需要分情况匹配,若开头为3,则只有30/31满足匹配
const reg = /^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/
reg.test("2022-03-22")

总结

这篇文章算是一个正则表达式非常基础的入门篇吧,所涉及的正则表达式的内容也非常有限,只是以我平时的实际例子作为引子,希望能够给想了解正则表达式的朋友们做个简单的浏览,如果想更进一步系统的学习正则表达式,请阅读以下参考文章,各位前辈大佬们已经总结得很精辟了,大家可以移步拜读拜读!

参考链接

JS正则表达式完整教程(略长)[强烈推荐]
学会正则很简单,前端大佬悉心整理的正则表达式笔记
三十分钟包会——正则表达式

往期好文推荐

面试官:说说从输入 URL 到页面显示到底经历了什么,体现一下你的知识广度

面试官:作为前端,服务器相关了解多少?

面试官:HTTPS 采用的是对称加密还是非对称加密?具体说说其加密过程

面试官:说说 Cookie 和 Token 的区别?

面试官:网络安全了解多少,简单说说?(一)

面试官:网络安全了解多少,简单说说?(二)

面试官:网络安全了解多少,简单说说?(三)

面试官:网络安全了解多少,简单说说?(四)

面试官:网络安全了解多少,简单说说?(五)

面试官:网络安全了解多少,简单说说?(六)

面试官:网络安全了解多少,简单说说?(七)

面试官:网络安全了解多少,简单说说?(八)

浅尝 | 从 0 到 1 Vue 组件库封装

面试官:这么简单的正则表达式都不会?

Webpack 打包类库踩坑

面试官:你就只会 npm run build 吗?(Webpack 配置 Vue+Ts)

面试官:连VuePress都没搭过还说开发过组件库?(VuePress 搭建)

面试官: 连 Vue 视图更新都不会写?(Vue视图更新原理【一】)

面试官: 能不能手写 Vue 响应式?(Vue2 响应式原理【完整版】)

面试官:能不能手写 Vue3 响应式(Vue3 原理解析之响应系统的实现)

JS 优雅之道(JS 代码优化小 Tip)

面试官:你真的会用 SVG 吗? (SVG 应用实战)

面试官:说一下这个Loading动画实现思路 (CSS3 实现 Loading 动画)

JS 扫盲题 ( 面试题梳理系列 (一))

面试官:你确定你说的防抖不是节流吗?( 面试题梳理系列 (二))

面试官:除了 HTTP,你还用过什么通信协议?(Websocket 在数字孪生中的应用)

面试官:你真的理解 Event Loop 吗?( JS 事件循环 )

面试官:v-for 中 key 为什么不能用 index,从原理层面聊聊?

面试官:vue-router 的 hash 与 history 哪个模式会刷新页面?

面试官:说说你平时用过的自适应方案(数字孪生可视化自适应方案)

面试官:说一下如何优化过渡动画(数字孪生可视化过渡动画)

写在最后

博主接下来将持续更新好文,欢迎关注博主哟!!
如果文章对您有帮助麻烦亲点赞、收藏 + 关注和博主一起成长哟!!❤️❤️❤️