javascript正则深入以及10个非常有意思的正则实战

徐小夕 等级 338 0 0

前言

熟悉我的朋友可能会知道,我一向是不写热点的。为什么不写呢?是因为我不关注热点吗?其实也不是。有些事件我还是很关注的,也确实有不少想法和观点。 但我一直奉行一个原则,就是:要做有生命力的内容

对于前端工程师来说, 正则表达式也许是javascript语言中最晦涩难懂的, 但是也往往是最简洁的.工作中遇到的很多问题,诸如搜索,查找, 高亮关键字等都可以使用正则轻松解决,所以有句话说的好:

正则用的好, 加班远离我.

今天笔者就复盘一下javascript正则表达式的一些使用技巧和高级API, 并通过几个实际的案例,来展现正则表达式的魅力.如果大家觉得正则表达式理解起来很麻烦,也可以使用如下在线网站, 只需要输入你的正则表达式, 它就能以图形的方式将你的正则展示出来: javascript正则深入以及10个非常有意思的正则实战

你将收获

  • 模式匹配的用法(x)
  • 非捕获括号的模式匹配(?:x)
  • 先行断言x(?=y)
  • 后行断言(?<=y)x
  • 正向否定查找x(?!y)
  • 反向否定查找(?<!y)x
  • 字符集合和反向字符集合的用法[xyz]/[^xyz]
  • 词边界和非单词边界匹配/b/B
  • 空白字符/非空白字符匹配/s/S
  • 单字字符/非单字字符匹配/w/W
  • 正则10大应用案例

正文

对于正则的基本用法笔者这里就不总结了,这里重点介绍一些比较有用且难懂的知识点.在最后笔者会写10个经典的正则案例, 供大家学习参考, 或者在工作中直接使用. javascript正则深入以及10个非常有意思的正则实战 以上几点应用笔者在下文中会写几个例子来讲解.

模式匹配的用法(x)

模式匹配主要用来匹配某一类字符串并记住匹配项.

案例:

let str = 'xuxi is xuxi is'
let reg = /(xuxi) (is) \1 \2/g
reg.test(str)  // true    (1)
str.replace(reg, '$1 $2')  // xuxi is  (2)

解释: 其中括号被称为捕获括号, 模式中的 \1 和 \2 表示第一个和第二个被捕获括号匹配的子字符串,即 xuxi 和 is,匹配了原字符串中的后两个单词, 因此(1)中运行的结果为true. 当我们在字符串中使用replace时, 我们可以使用$1, $2这样的方式获取第n个匹配项,并用来替换字符串. 如(2)中的运行结果.

非捕获括号的模式匹配(?:x)

主要用来匹配某一类字符串但不记住匹配项.

案例:

let str = 'xuxixuxi'
let reg = /(?:xuxi){1,2}/g
reg.test(str)  // true    (1)

javascript正则深入以及10个非常有意思的正则实战 解释: 其中(?:)被称为非捕获括号, 我们可以使用它匹配一组字符但是并不记住该字符,一般用来判断某类字符是否存在于某字符串中.

先行断言x(?=y)

先行断言: 匹配'x'仅仅当'x'后面跟着'y'.

案例:

let str = '王者融化'
let reg = /王(?=者)/
reg.test(str)  // true    (1)

javascript正则深入以及10个非常有意思的正则实战 解释: /王(?=者)/会匹配到"王"仅当它后面跟着"者".但是"者"不属于匹配结果的一部分.

后行断言(?<=y)x

后行断言: 匹配'x'仅当'x'前面是'y'.

案例:

let str = 'xuxiA'
let reg = /(?<=xuxi)A/
reg.test(str)  // true    (1)

解释: /(?<=xuxi)A/会匹配到A仅当它前面为xuxi.但是xuxi不属于匹配结果的一部分.

正向否定查找x(?!y)

正向否定查找: 仅仅当'x'后面不跟着'y'时匹配'x'.

案例:

let str = '3.1415'
let reg = /\d+(?!\.)/
reg.exec(str)  // [1415]   (1)

javascript正则深入以及10个非常有意思的正则实战 解释: 其中/\d+(?!.)/匹配一个或多个数字,当且仅当它后面没有小数点时, 所以(1)中执行后会匹配到1415而不是3.1415

反向否定查找(?<!y)x

反向否定查找: 仅仅当'x'前面不是'y'时匹配'x'.

案例:

let str = '3.1415'
let reg = /(?<!\.)\d+/
reg.exec(str)  // [3]    (1)

解释: /(?<!.)\d+/匹配一个数字,当且仅当前面字符不是.时,此时将匹配3.

字符集合和反向字符集合的用法 [xyz] / [^xyz]

[xyz]: 一个字符集合。匹配方括号中的任意字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。

[^xyz]: 一个反向字符集。也就是说,它匹配任何没有包含在方括号中的字符。你可以使用破折号(-)来指定一个字符范围。任何普通字符在这里都是起作用的

案例:

let str = 'abcd'
let reg1 = /[a-c]+/
let reg2 = /[^d]$/
reg1.test(str)  // true    (1)
reg2.test(str)  // false    (2)

javascript正则深入以及10个非常有意思的正则实战 javascript正则深入以及10个非常有意思的正则实战

解释: (1)中将返回true因为字符串中包含a-c中的字符, (2)中奖返回false, 因为字符串结尾为d, 但正则reg2需要匹配结尾不为d的字符串.

词边界和非单词边界匹配\b\B

\b 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0。

\B 匹配一个非单词边界。匹配如下几种情况: (1)字符串第一个字符为非“字”字符 (2)字符串最后一个字符为非“字”字符 (3)两个单词字符之间 (4)两个非单词字符之间 (5)空字符串

案例:

let str = 'xuxi'
let reg1 = /xi\b/
let reg2 = /xu\B/
reg1.exec(str)  // [xi]    (1)
reg2.exec(str)  // [xu]    (2)

javascript正则深入以及10个非常有意思的正则实战 javascript正则深入以及10个非常有意思的正则实战 解释: (1)中匹配到了单词边界,即xi, 为该字符串的末尾.(2)中应为xu为非单词边界,所以会被其匹配到.

空白字符/非空白字符匹配\s\S

\s: 匹配一个空白字符,包括空格、制表符、换页符和换行符.

\S: 匹配一个非空白字符

案例:

let str = 'xuxi is'
let reg1 = /.*\s/g
let reg2 = /\S\w*/g
reg1.exec(str)  // [xuxi]    (1)
reg2.exec(str)  // [xuxi]    (2)

javascript正则深入以及10个非常有意思的正则实战 javascript正则深入以及10个非常有意思的正则实战 解释: (1)和(2)中执行之后都将匹配xuxi, 一个是空白字符之前的匹配, 一个是非空白字符的匹配.

单字字符/非单字字符匹配\w/W

\w: 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]。

\W: 匹配一个非单字字符。等价于 [^A-Za-z0-9_]

javascript正则深入以及10个非常有意思的正则实战 javascript正则深入以及10个非常有意思的正则实战 由于以上2种模式比较简单,这里就不一一介绍了.

正则10大应用案例

接下来笔者将总结几个使用正则的实际应用,供大家学习和参考.

1. 去除字符串内指定元素的标签

function trimTag(tagName, htmlStr) {
  let reg = new RegExp(`<${tagName}(\\s.*)*>(\\n|.)*<\\/${tagName}>`, "g")
  return htmlStr.replace(reg, '')
}

2. 短横线命名转驼峰命名

// 短横线转驼峰命名, flag = 0为小驼峰, 1为大驼峰
function toCamelCase(str, flag = 0) {
  if(flag) {
    return str[0].toUpperCase() + str.slice(1).replace(/-(\w)/g, ($0, $1) => $1.toUpperCase())
  }else {
    return str.replace(/-(\w)/g, ($0, $1) => $1.toUpperCase())
  }
}

3. 实现一个简单的模板引擎

关于实现一个模板引擎, 实现中用到了大量的正则,建议感兴趣的可以直接看实现一个简单的模板引擎.

4. 去除字符串中的空格符

function trimAll(str) {
  return str.replace(/\s*/g,"")
}

5. 判断指定格式的数据输入合法性

function numCheck(str, specialNum) {
  if(str.indexOf(',') > -1) {
      return str.split(',').every(item=>this.numCheck(item));
  } else {
      return str.split(specialNum).length === 2;
  }
}

6. 去除url参数字符串中值为空的字段

// 去除url参数字符串中值为空的字段
const trimParmas = (parmaStr:string = '') => {
  return parmaStr.replace(/((\w*?)=&|(&\w*?=)$)/g, '')
}

7. 将浏览器参数字符串转化为参数对象

function unParams(params = '?a=1&b=2&c=3') {
  let obj = {}
  params && params.replace(/((\w*)=([\.a-z0-9A-Z]*)?)?/g, (m,a,b,c) => {
    if(b || c) obj[b] = c
  })
  return obj
}

8. 计算字符串字节数

/**
 * 计算字符串字节数
 * @param str
 * @desc 一个中文占2个字节, 一个英文占一个字节
 */
function computeStringByte(str) {
  let size = 0,
  strArr = str.split(''),
  reg = /[\u4e00-\u9fa5]/   // 判断是否为中文
  for(let i = strArr.length; i--; i>=0) {
    if(reg.test(strArr[i])) { 
      size+= 2
    }else {
      size += 1
    }
  }
  return size
}

9. 匹配是否包含中文字符

function hasCn(str) {
  let reg = /[\u4e00-\u9fa5]/g
  return reg.test(str)
}

10. 实现搜索联想功能

function searchLink(keyword) {
  // 模拟后端返回数据
  let list = ['abc', 'ab', 'a', 'bcd', 'edf', 'abd'];
  let reg = new RegExp(keyword, 'i');
  return list.filter(item => reg.test(item))
}

最后

如果想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们的技术群一起学习讨论,共同探索前端的边界。 javascript正则深入以及10个非常有意思的正则实战

更多推荐

收藏
评论区

相关推荐

基于 localStorage 实现一个具有过期时间的 DAO 库
本文主要解决原生localStorage无法设置过期时间的问题,并通过封装,来实现一个操作便捷,功能强大的localStorage库,关于库封装的一些基本思路和模
教你用200行代码写一个爱豆拼拼乐H5小游戏(附源码)
前言 本文将带大家一步步实现一个H5拼图小游戏,考虑到H5游戏的轻量级和代码体积,我没有使用react或vue这些框架,而采用我自己写的dom库和原生javascript来实现业务功能,具体库代码可见我的文章如何用不到200行代码写一款属于自己的js类库(https://juejin.im/post/6844903880707293198),构建工具我采
What the f*ck JavaScript?
What the fck JavaScript? 一个有趣和棘手的 JavaScript 示例列表。 JavaScript 是一种很好的语言。
笛卡尔乘积的javascript版实现和应用
笛卡尔乘积是指在数学中,两个集合X和Y的笛卡尓积,又称直积,表示为X × Y,第一个对象是X的成员而第二个对象是Y的所有可能有序对的其中一个成员 。 例子 假设集合A{a, b},集合B{0, 1, 2},则两个集合的笛卡尔积为{(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}。 (https:
《前端实战总结》之使用解释器模式实现获取元素Xpath路径的算法
前端领域里基于javascript的设计模式和算法有很多,在很多复杂应用中也扮演着很重要的角色,接下来就介绍一下javascript设计模式中的解释器模式,并用它来实现一个获取元素Xpath路径的算法。 上期回顾 《前端实战总结》之迭代器模式的N1种应用场景(https://juejin.im/post/6844904008616771591)
JavaScript中的类型
JavaScript中的类型 一、关于类型 什么叫做类型?简单地说,类型就是把内存中的一个二进制序列赋予某种意义。比如,二进制序列0100 0000 0111 0000 0001 0101 0100 1011 1100 0110 1010 0111 1110 1111 1001 1110如果看作是64位无符号整数类型就是4
使用Intersection Observer API实现视频队列自动播放
前言 笔者利用空余时间研究了一下javascript的Intersection Observer API,发现其有很大的应用场景,比如图片或者内容的懒加载,视差动画等。笔者也在之前的文章中详细介绍了3种Observer(观察者)的用法,包括位置监听,dom变化监听以及窗口变化监听,它们有非常多的应用场景,所以很有必要研究明白, 感兴趣的可以读完本片文章之后学
舒文:浅谈阿里前端的多样化
2007年,Jeff Atwood 提出了一个著名的观点, 戏谑又似认真地称其为 Atwood's Law(https://blog.codinghorror.com/theprincipleofleastpower/): _any application that can be written in JavaScript, will event
巨大提升!更快的 async 函数和 promises
(https://imghelloworld.osscnbeijing.aliyuncs.com/669a1c8f7203559afa4621628303674c.png) 翻译自:Faster async functions and promises(https://v8.dev/blog/fastasync) JavaScript
JavaScript中本地存储的方式有哪些?
(https://imghelloworld.osscnbeijing.aliyuncs.com/1f907f0895e2be23aa56604dd42e3626.png) 一、方式 javaScript本地缓存的方法我们主要讲述以下四种: cookie sessionStorage loc
14个优秀 JS 前端框架、库、工具及其使用时机
  这篇文章主要描述现今流行的一些 Javascript web 前端框架,库以及它们的适用场景。   新的 Javascript 库层出不穷,从而Web 社区愈发活跃、多样、在多方面快速发展。详细去描述每一种主流的 Javascript 框架和库近乎
JavaScript 是什么?
前言 引用《JavaScript 高级程序设计第四版》中说的话 ——“从简单的输入验证脚本到强大的编程语言,JavaScript 的崛起没有任何人预测到。它很简单,学会用只要几分钟;它又很复杂,掌握它要很多年。要真正学好用好 JavaScript,理解其本质、历史及局限性是非常重要的”。 面试官:JavaScript 是什么? 我:
理解 Javascript 中的 Async / Await
在本文中,我们将探讨async/await,对于每个Javascript开发人员来说,是异步编程的首选工具。如果您不熟悉javascript,请不要担心,本文将帮助您async/await从头开始理解。 介绍async/await 是javascript中的一种模式,可使您的代码以同步方式执行,但又不影响javascript的异步行为。 定义异步功能要定义一
JavaScript 和 Node.js 中事件循环
1.JavaScript中事件循环可以参考《JavaScript忍者秘籍第二版》第十三章,讲解的很好。JavaScript中事件循环,主要就在理解宏任务和微任务这两种异步任务。宏任务(macrotask): setTimeOut 、 setInterval 、 setImmediate 、 I/O 、 各种callback、 UI渲染 、messageCh
了解什么是 TypeScript
内容纲要 了解什么是 TypeScript TypeScript 基本语法 TypeScript 介绍 TypeScript 是什么TypeScript 是 JavaScript 的强类型版本。然后在编译期去掉类型和特有语法,生成纯粹的 JavaScript代码。由于最终在浏览器中运行的仍然是 JavaScript,所以 TypeScript 并