最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 简单正则一手掌握

    正文概述 掘金(幻灵尔依)   2020-12-17   395

    据我了解正则表达式好像只有前端掌握的不好,这可能跟大部分前端写正则比较少、用到的正则比较简单有关。正则表达式的能力似乎被前端大大低估了。

    我基本也是用到了正则才会回头看看收藏的文章,写出来自己想要的正则就完事了,对正则的感觉一直是一知半解。凑巧前几天在搞富文本编辑器,用到了一些稍微复杂的正则,这才又回头看了一遍收藏夹。这次的感觉仿佛跟以前不一样了。

    字符(建议稍稍熟悉的跳过,看一遍并不能记住)

    正则中很多需要强记的字符,这里列出常用的字符和其表达的含义:

    常用匹配字符含义
    [0-9]匹配单个数字0-9[a-z]匹配单个小写字母[A-Z]匹配单个大写字母\s匹配所有空白字符,如空格、换行等\n匹配所有换行符\b匹配边界如字符之间的空格
    特殊字符含义用法
    ^1. 匹配输入字符串的开始位置 2. 用在[]中时表示 非1. /^http/ 匹配以http开头的字符串 2. /[^a-zA-Z]/ 匹配非字母$匹配输入字符串的结尾位置/.com$/ 匹配以.com结尾的字符串|二选一,表示 或/a|b/ 匹配a或者b.小数点匹配换行符\n之外的任何单个字符/./ 匹配换行符之外的其他字符[]中括号匹配一个字符/[aeiou]/ 匹配字母 aeiou 中的一个()小括号表示一个子表达式分组匹配的子表达式可以用于以后使用{}大括号表示限定一个表达式多少次{n} 匹配n次; {n,} 匹配最少n次; {n, m} 匹配n-m次+匹配前面的子表达式一次或多次/[0-9]+/ 匹配一个数字或多个数字*匹配前面的子表达式零次或多次/[0-9]*/ 匹配0次数字或多个数字?1. 匹配前面的子表达式零次或一次 2. 指明一个非贪婪限定符1. /[0-9]?/ 2. /<.*?>/ 匹配一个标签如<p>
    匹配字符本身时需要转义的特殊字符共有以下几个(其中 / 在字面量中需要转义,在构造函数中不需要):
    * . ? + $ ^ [ ] ( ) { } | \ /
    

    常用方法

    js 中的正则表达式分为字面量和构造函数两种:

    // 字面量
    const reg = /[0-9a-z]/g
    // 构造函数
    const reg = new RegExp('[0-9a-z]', 'g')
    

    其中字面量中不能包含变量,构造函数中可以使用变量:

    const name = '幻灵尔依'
    const reg = new RegExp(`我的名字叫${name}`)
    

    经常会用 reg.test(str) 方法来判断字符串中是否匹配到了正则表达式:

    const reg = /[0-9]/
    const str = '文本中有没有数字1234等'
    if (reg.test(str)) {
      ...
    }
    

    也经常用str.replace(reg, '') 方法来替换字符串中的内容:

    const reg = /[0-9]/g
    const str = '文本中的数字1234全部替换成x'
    const newStr = str.replace(reg, 'x')
    

    也会用到 str.match(reg) 方法来获取匹配到的内容(也可以用reg.exec(str)):

    const reg = /[0-9]+[.][0-9]+[.][0-9]+/g
    const str = '这里有个表名字叫做 11.11.11'
    str.match(reg) // ['11.11.11']
    
    • match 中的正则表达式如果使用g标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。
    • 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(Array)。 在这种情况下,返回的项目将具有如下所述的其他属性。

    贪婪&非贪婪

    * 和 + 限定符都是贪婪的,它们会尽可能多的匹配文字。在它们的后面加上一个 ? 就可以实现非贪婪或最小匹配。

    • 贪婪(默认都是贪婪的)
    const str = '<h1>正则表达式</h1>'
    const reg = /<.*>/
    str.match(reg) // ['<h1>正则表达式</h1>']
    
    • 非贪婪
    
    const str = '<h1>正则表达式</h1>'
    const reg = /<.*?>/
    str.match(reg) // ['<h1>']
    

    捕获分组和回溯引用

    小括号 () 匹配到的子表达式会被缓存为一个个组,方便后面对其引用。假设要获取html中的 h1 标签:

    • 在正则表达式中使用 \n 可以引用第n个捕获组
    const str = '<p>正则表达式</p><h1>正则表达式</h1><h2>正则表达式</h2>'
    const reg = /<(h1)>.+?<\/\1>/
    str.match(reg) // ['<h1>正则表达式</h1>']
    
    • 在正则表达式外使用 $n 引用第n个捕获组(RegExp.$n)
    const str = 'abc'
    const reg = /(abc)/
    RegExp.$1 // 'abc'
    str.replace(reg, '$1$1') // 'abcabc'
    

    非捕获分组和限定查找

    因为捕获组 () 会将每个捕获到的结果缓存下来以便引用,所以会造成内存使用增加。如果只是想用分组的原始功能,而不需要缓存,则可以使用非捕获分组 (?:)

    const str = 'abc'
    const reg = /(?:abc)/
    RegExp.$1 // ''
    

    非捕获分组还有 (?=)、(?<=)、(?!)、(?<!) ,他们比 (?:) 多了限定作用,即只匹配而不会被输出。

    前向查找

    前向查找是用来限制后缀的。

    1. (?=): 即查找符合限定条件 (?=) 的前面的匹配项(输出内容不包括 (?=) 中的匹配项)
    const str = 'a.png b.jpg c.gif d.svg'
    // 查找所有 边界开头的、 .svg 前面的 小写字母。
    const reg = /\b[a-z](?=.svg)/g
    str.match(reg) // ['d']
    
    1. (?!): 即查找 不符合 限定条件 (?!) 的前面的匹配项(输出内容不包括 (?!) 中的匹配项)
    const str = 'a.png b.jpg c.gif d.svg'
    // 查找所有边界开头的、 非.svg 前面的、 `.[a-z]{3}` 前面的 小写字母。
    const reg = /\b[a-z](?!.svg)(?=\.[a-z]{3})/g
    str.match(reg) // ['a', 'b', 'c']
    

    后向查找

    后向查找是用来限制前缀的。

    1. 查找符合限定条件 (?<=) 的后面的匹配项(输出内容不包括 (?<=) 中的匹配项)
    const str = '1. 1111; 2. 2222; 3. 3333; 4. 4444。'
    //  查找所有 序号 后面的项。
    const reg = /(?<=\b[0-9]+\.\s).+?[;。]/g
    str.match(reg) // ["1111;", "2222;", "3333;", "4444。"]
    
    1. 查找 不符合 限定条件 (?<!) 的后面的匹配项(输出内容不包括 (?<!) 中的匹配项)
    const str = 'a.png b.jpg c.gif d.svg'
    // 查找前缀不为 a b c 的后面的项
    const reg = /\b(?<![abc]\.)[a-z]{3}/g
    str.match(reg) // ['svg']
    

    来个能吃的栗子

    一般稍微复杂的正则都是多种规则同时使用的,下面来几个例子吧:

    前向查找和后向查找齐用:

    假设要获取 <img crossorigin src="https://abcdefg.com" data-img-url="https://test.com"> 中的 data-img-url 属性中的链接。可以确定的是链接左边一定是 data-img-url=" ,右边一定是紧贴着 " (非贪婪)。

    const str = '<img crossorigin src="https://abcdefg.com" data-img-url="https://test.com">'
    const dataImgUrl = 'data-img-url'
    const reg = new RegExp(`(?<=${dataImgUrl}=").+?(?=")`, 'g')
    str.match(reg) // ['https://test.com']
    

    回溯引用和非贪婪并用

    假如我要获取一段html中的文本,但是我又不想要加了 not-show-in-text 标记的标签中的文本,可以这样:

    const notShowInText = 'not-show-in-text'
    const html = `
      <p>test1</p>
      <p ${notShowInText} style="text-align: center;">
        <b>表 1.4.4 测试表格</b>
      </p>
      <p>test2</p>
    `
    const reg = new RegExp(`<([a-z][a-z1-6]*?)[^>]+${notShowInText}[\\s\\S]+?</\\1>`, 'g')
    const text = html.replace(reg, '').replace(/<[^>]+>/g, '')
    

    其中最关键的是要匹配到 not-show-in-text 所在的整个标签。([a-z][a-z1-6]*?) 匹配了一个非贪婪的标签名,[^>] 保证了 <> 是一个半个完整的标签,</\\1> 匹配一个闭合的标签, [\\s\\S]+? 匹配了标签见可能出现的任意元素且是非贪婪的。

    replace第二个参数可以是回调函数

    比如,想把 yyyy-mm-dd 格式,替换成 mm/dd/yyyy 怎么做?

    var regex = /(\d{4})-(\d{2})-(\d{2})/;
    var string = "2017-06-12";
    var result = string.replace(regex, "$2/$3/$1");
    console.log(result); // "06/12/2017"
    

    其中 replace 第二个参数里用$1、$2、$3指代相应的分组。等价于如下的形式:

    var regex = /(\d{4})-(\d{2})-(\d{2})/;
    var string = "2017-06-12";
    var result = string.replace(regex, function() {
    	return RegExp.$2 + "/" + RegExp.$3 + "/" + RegExp.$1;
    });
    console.log(result); // "06/12/2017"
    

    也等价于:

    var regex = /(\d{4})-(\d{2})-(\d{2})/;
    var string = "2017-06-12";
    var result = string.replace(regex, function(match, year, month, day) {
    	return month + "/" + day + "/" + year;
    });
    console.log(result); // "06/12/2017"
    

    本文参考

    • 正则表达式不要背
    • 正则表达式括号的作用

    起源地下载网 » 简单正则一手掌握

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元