前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如果当时学会了这7个高频正则表达式,我的面试一定不会输!

如果当时学会了这7个高频正则表达式,我的面试一定不会输!

作者头像
前端胖头鱼
发布2022-07-25 08:38:54
7110
发布2022-07-25 08:38:54
举报
文章被收录于专栏:胖头鱼学前端

前言

最近是跳槽高峰期啊!好几个同事跳字节美团阿里,薪资涨了一大波,羡慕的我心痒痒,人和人的差距怎么这么大,不由得觉得自己是个垃圾!

趁机问了一波这些大厂都面哪些题,其中不乏源码分析算法计算机网络JS基础前端工程等等,不过有个小点似乎大家都遇到了,就是正则表达式,虽然说他们都拿到了offer,但是正则匹配答的不太好,不由得让我想起了以往的面试,也是该死的正则输了阵。

今天胖头鱼试着把前端面试中常见的正则表达式相关的题都捞一遍,希望以后正则这个点直接过

1.提取连续重复的字符

币安原题 将有重复的字符提取出来,例如12323454545666,提取[ '23', '45', '6' ]

正则结果

代码语言:javascript
复制
const collectRepeatStr = (str) => {
  let repeatStrs = []
  const repeatRe = /(.+)\1+/g
  
  str.replace(repeatRe, ($0, $1) => {
    $1 && repeatStrs.push($1)
  })
  
  return repeatStrs
}

分析过程

题目中有几个关键信息是

  1. 连续重复的字符
  2. 连续重复的字符数的长度是不限的(如23、45是两位、6是一位)

那什么是连续重复呢?

11是连续重复、22也是连续重复、111当然也是。也就是说某些字符X之后一定也是跟着X,就叫连续重复。如果很明确知道X就是1,那么/11+/也就可以匹配了,但关键是这里的X是不明确的,怎么办呢?。

使用反向引用的正则知识可以很方便解决这个问题。

第一步,写出表示有一个字符重复的正则

代码语言:javascript
复制
// 这里的X可用.来表示,即所有的字符,并用括号进行引用,紧跟着反向应用\1,也就是体现了连续重复的意思啦
let repeatRe = /(.)\1/

console.log(repeatRe.test('11')) // true
console.log(repeatRe.test('22')) // true
console.log(repeatRe.test('333')) // true
console.log(repeatRe.test('123')) // false

第二步,写出表示有n个字符重复的正则

因为并不确定是要匹配11还是45 45所以括号内需要用量词+来体现n个重复字符,而反向引用本身也可以是大于一个的,例如 45 45 45

代码语言:javascript
复制

let repeatRe = /(.+)\1+/

console.log(repeatRe.test('11')) // true
console.log(repeatRe.test('22')) // true
console.log(repeatRe.test('333')) // true
console.log(repeatRe.test('454545')) // true
console.log(repeatRe.test('124')) // false

第三步,提取所有连续重复的字符

代码语言:javascript
复制

const collectRepeatStr = (str) => {
  let repeatStrs = []
  const repeatRe = /(.+)\1+/g
  // 很多时候replace并不是用来做替换,而是做数据提取用
  str.replace(repeatRe, ($0, $1) => {
    $1 && repeatStrs.push($1)
  })
  
  return repeatStrs
}


console.log(collectRepeatStr('11')) // ["1"]
console.log(collectRepeatStr('12323')) // ["23"]
console.log(collectRepeatStr('12323454545666')) // ["23", "45", "6"]

2. 实现一个trim函数

老生常谈的题了,这里我们用两种思路实现 去除字符串的首尾空格

正则结果

代码语言:javascript
复制
// 去除空格法
const trim = (str) => {
  return str.replace(/^\s*|\s*$/g, '')    
}
// 提取非空格法
const trim = (str) => {
  return str.replace(/^\s*(.*?)\s*$/g, '$1')    
}

image.png

image.png

分析过程

初看题目我们脑海中闪过的做法是把空格部分删除掉,保留非空格的部分,但是也可以换一种思路,也可以把非空格的部分提取出来,不管空格的部分。接下来我们来写一下两种trim方法的实现

方式一、去除空格法

代码语言:javascript
复制

const trim = (str) => {
  return str.replace(/^\s*|\s*$/g, '')    
}

console.log(trim('  前端胖头鱼')) // 前端胖头鱼
console.log(trim('前端胖头鱼  ')) // 前端胖头鱼 
console.log(trim('  前端胖头鱼  ')) // 前端胖头鱼
console.log(trim('  前端 胖头鱼  ')) // 前端 胖头鱼

方式二、提取非空格法

代码语言:javascript
复制

const trim = (str) => {
  return str.replace(/^\s*(.*?)\s*$/g, '$1')    
}

console.log(trim('  前端胖头鱼')) // 前端胖头鱼
console.log(trim('前端胖头鱼  ')) // 前端胖头鱼 
console.log(trim('  前端胖头鱼  ')) // 前端胖头鱼
console.log(trim('  前端 胖头鱼  ')) // 前端 胖头鱼

3. 数字价格千分位分割

将123456789变成123,456,789

这道题估计大家在面试和工作中也经常遇到,出现频率比较高。

正则结果

代码语言:javascript
复制
'123456789'.replace(/(?!^)(?=(\d{3})+$)/g, ',') // 123,456,789

image.png

补充小数千分位支持

carbon.png

分析过程

题目意思大概是:

  1. 从后往前每三个数字前加一个逗号
  2. 开头不能加逗号(比如:123 最后不能变成,123)

是不是很符合(?=p)的规律呢?p可以表示每三个数字,要添加的逗号所处的位置正好是(?=p)匹配出来的位置。

第一步,尝试先把后面第一个逗号弄出来

代码语言:javascript
复制

let price = '123456789'
let priceReg = /(?=\d{3}$)/

console.log(price.replace(proceReg, ',')) // 123456,789

第二步,把所有的逗号都弄出来

要把所有的逗号都弄出来,主要要解决的问题是怎么表示三个数字一组,也就是3的倍数。我们知道正则中括号可以把一个p模式变成一个小整体,所以利用括号的特性,可以这样写

代码语言:javascript
复制

let price = '123456789'
let priceReg = /(?=(\d{3})+$)/g

console.log(price.replace(priceReg, ',')) // ,123,456,789

第三步,去掉首位的逗号,

上面已经基本上实现需求了,但是还不够,首位还会出现逗号,那怎么把首位的逗号去除呢?想想是不是有一个知识正好满足这个场景?没错(?!p),就是他了,两者结合就是从后往前每三个数字的位置前添加逗号,但是这个位置不能是^首位。

代码语言:javascript
复制

let price = '123456789'
let priceReg = /(?!^)(?=(\d{3})+$)/g

console.log(price.replace(priceReg, ',')) // 123,456,789

4. 手机号3-4-4分割

将手机号18379836654转化为183-7983-6654

表单搜集场景,经常遇到的手机格式化

正则结果

代码语言:javascript
复制
let mobile = '18379836654' 
let mobileReg = /(?=(\d{4})+$)/g 

console.log(mobile.replace(mobileReg, '-')) // 183-7983-6654

image.png

分析过程

有了上面数字的千分位分割法,做这个题相信会简单很多,也就是从后往前找到这样的位置:

每四个数字前的位置,并把这个位置替换为-

代码语言:javascript
复制

let mobile = '18379836654'
let mobileReg = /(?=(\d{4})+$)/g

console.log(mobile.replace(mobileReg, '-')) // 183-7983-6654

5. 将字符串驼峰化

如下规则,将对应字符串变成驼峰写法

代码语言:javascript
复制
1. foo Bar => fooBar

2. foo-bar---- => fooBar

3. foo_bar__ => fooBar

正则结果

代码语言:javascript
复制
const camelCase = (string) => {
  const camelCaseRegex = /[-_\s]+(.)?/g

  return string.replace(camelCaseRegex, (match, char) => {
    return char ? char.toUpperCase() : ''
  })
}

image.png

分析过程

分析题目的规律

  1. 每个单词的前面都有0个或者多个- 空格 _ 如(Foo--foo__FOO_BARBar)
  2. - 空格 _后面有可能不跟任何东西 如(__--)
代码语言:javascript
复制
const camelCase = (string) => {
  // 注意(.)?这里的?是为了满足条件2
  const camelCaseRegex = /[-_\s]+(.)?/g

  return string.replace(camelCaseRegex, (match, char) => {
    return char ? char.toUpperCase() : ''
  })
}

console.log(camelCase('foo Bar')) // fooBar
console.log(camelCase('foo-bar--')) // fooBar
console.log(camelCase('foo_bar__')) // fooBar

6. 将字符串首字母转化为大写,剩下为小写

例如 hello world 转为为Hello World

正则结果

代码语言:javascript
复制

const capitalize = (string) => {
  const capitalizeRegex = /(?:^|\s+)\w/g

  return string.toLowerCase().replace(capitalizeRegex, (match) => match.toUpperCase())
}

image.png

分析过程

找到单词的首字母然后将其转化为大写字母就可以,单词前面可能是开头也可能是多个空格

代码语言:javascript
复制

const capitalize = (string) => {
  const capitalizeRegex = /(?:^|\s+)\w/g

  return string.toLowerCase().replace(capitalizeRegex, (match) => match.toUpperCase())
}

console.log(capitalize('hello world')) // Hello World
console.log(capitalize('hello WORLD')) // Hello World

7.通过name获取url query参数

正则结果

代码语言:javascript
复制
const getQueryByName = (name) => {
  const queryNameRegex = new RegExp(`[?&]${name}=([^&]*)(&|$)`)
  const queryNameMatch = window.location.search.match(queryNameRegex)
  // 一般都会通过decodeURIComponent解码处理
  return queryNameMatch ? decodeURIComponent(queryNameMatch[1]) : ''
}

分析过程

url query上的参数 name=前端胖头鱼 所处的位置可能是

  1. 紧跟着问号 ?name=前端胖头鱼&sex=boy
  2. 在最后的位置 ?sex=boy&name=前端胖头鱼
  3. 在1和2之间 ?sex=boy&name=前端胖头鱼&age=100

所以只要处理三个地方基本就可以通过正则来取了

  1. name前面只能是?或者&
  2. value的值可以除了是&以为的任意东西
  3. value后面只能是跟着&或者是结束位置
代码语言:javascript
复制

const getQueryByName = (name) => {
  const queryNameRegex = new RegExp(`[?&]${name}=([^&]*)(?:&|$)`)
  const queryNameMatch = window.location.search.match(queryNameRegex)
  // 一般都会通过decodeURIComponent解码处理
  return queryNameMatch ? decodeURIComponent(queryNameMatch[1]) : ''
}
// 1. name在最前面
// https://juejin.cn/?name=前端胖头鱼&sex=boy
console.log(getQueryByName('name')) // 前端胖头鱼

// 2. name在最后
// https://juejin.cn/?sex=boy&name=前端胖头鱼
console.log(getQueryByName('name')) // 前端胖头鱼


// 2. name在中间
// https://juejin.cn/?sex=boy&name=前端胖头鱼&age=100
console.log(getQueryByName('name')) // 前端胖头鱼

结尾

这7个正则表达式面试题是胖头鱼和其他几个朋友面试中遇到比较多,如果你有其他正则相关的面试题,欢迎补充哈。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端胖头鱼 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 1.提取连续重复的字符
    • 正则结果
      • 分析过程
      • 2. 实现一个trim函数
        • 正则结果
          • 分析过程
          • 3. 数字价格千分位分割
            • 正则结果
              • 分析过程
              • 4. 手机号3-4-4分割
                • 正则结果
                  • 分析过程
                  • 5. 将字符串驼峰化
                    • 正则结果
                      • 分析过程
                      • 6. 将字符串首字母转化为大写,剩下为小写
                        • 正则结果
                          • 分析过程
                          • 7.通过name获取url query参数
                            • 正则结果
                              • 分析过程
                              • 结尾
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档