【正则表达式系列】一些概念字符组、捕获组、非捕获组

前言

本文介绍一些正则中的常用名词以及对应概念,譬如字符组,捕获组、非捕获组、反向引用、转义和\s \b

大纲

  • 字符组
  • 捕获组
  • 反向引用
  • 非捕获组
  • .\s\S
  • \b
  • \转义

字符组

[]字符组表示在同一个位置可能出现的各种字符,也就是说它的匹配结果只能是一个字符,不能是多个

例如[hello]匹配的不是hello而是h或e或l或o

特点

  • 结果只会匹配一个字符
  • 内部特殊字符无需转义\ [ ] 除外

    • 另外,^出现在最开始位置时需要转义
    • -前后构成区间范围时需要转义(推荐永远使用转义\-
  • -表示连字符
  • ^表示排除符

示例

特殊字符无需转义

[\^*\-+|(a)]

这个示例的含义是,匹配以下字符中的任意一个

  • ^ * - + | ( a )
  • 可以看到,这些特殊字符在字符组中仅仅就是字符本身

连字符的作用

[z-a]

匹配这个正则表达式会报错(Range out of order in character class

原因是连字符后面的字符码要大于等于前面的字符码

var str = 'abc-';
var reg = /[a-z-]/g;

// 最后的连字符没有构成区间,所以仅仅表示  - 这个字符
str.match(reg); // ["a","b","c","-"]
var str = "aAbc-";
var reg = /[A-a-z]/g;

// 通用,A-a 构成一个区间  之后的 -z 无法构成区间,于是它只能作为-字符本身
str.match(reg); // ["a","A","-"]

排除型

var str = '01ABabc-';
var reg = /[^a-z]/g;

// 匹配了除a-z范围外的任意字符
str.match(reg); // ["0","1","B","-"]

排除型字符组用法和普通的一样,但是唯一区别是

  • 排除型代表符合条件的都不匹配(功能相反)

\b特殊情况

var str = 'ab\bd,cdef';
var reg = /[\b]/g;
var reg2 =  /\bc/g; 
var reg3 =  /[\b]c/g; 

str.match(reg); // [""] 匹配\b本身
str.match(reg2); // ["c"]  即匹配,号后面的c
str.match(reg3); // null 因为\b后面没有c
  • \b在字符组以外表示单词边界
  • 在字符组内,表示退格符(\b)

捕获组

捕获组就是把正则表达式中子表达式匹配的内容,保存到内存中以数字编号或显式命名的组里,方便后面引用

例如: /(a)(b)(c)/中的捕获组编号为

  • 0: abc
  • 1: a
  • 2: b
  • 3: c

其中,组0是正则表达式整体匹配结果,组1`2`3才是子表达式匹配结果

特点

  • 子表达式捕获组编号从1开始,顺序从左到右(例如编号1是左侧第一个()包裹的子表达式的结果)
  • 可以在正则表达式中对前面捕获的内容进行引用(反向引用)
  • 也可以在程序中,对捕获组捕获的内容进行引用(比如replace中)

示例

子表达式捕获组编号从1开始,顺序从左到右

var str = "2017-07-29";
var reg = /(\d{4})-(\d{2})-(\d{2})/;

// 非全局模式有捕获组结果
str.match(reg); // ["2017-07-29","2017","07","29",index: 0,input: "2017-07-29"]

上述匹配中,除了整个正则表达式的结果外,还有各个捕获组的结果,其中,子表达式的捕获组从编号1开始,如下

编号 捕获组 匹配内容
0 (d{4})-(d{2})-(d{2}) 2017-07-29
1 d{4} 2017
2 d{2} 07
3 d{2} 29

JS程序内的引用

  • replace中,JS通过$number引用捕获组内容
  • 在外部匹配引用,JS通过RegExp.$number引用捕获组内容
var str = '<div id="code1" class="highlight"></div>';
var reg = /<(\w+)[^>]*>/g;

// <div></div>
str = str.replace(reg,"<$1>");

可以看到,在去除div中的属性时,先是整个匹配<divxxx>,然后再把整个内容替换成<$1>,其中$1就是第一个捕获组结果div的引用

注,请不要引用$0,因为它不属于子表达式的捕获组,在replace中引用$0没有任何效果

var str = 'abcd0123ABCD';
var reg = /([a-z]+)(\d+)([A-Z]+)/g;

reg.test(str); // true

console.log(RegExp.$0); // undefined
console.log(RegExp.$1); // abcd
console.log(RegExp.$2); // 0123
console.log(RegExp.$3); // ABCD

注,同样$0的引用没有内容

反向引用

在正则表达式内部对捕获组进行引用称之为反向引用

var str = "boom==boom";
var reg = /(boom)==\1/;

str.match(reg); // ["boom==boom","boom",input: "boom==boom"]

可以看到,正则中\1的值就是捕获组1匹配到的结果boom

因此,这个表达式等价于(boom)==boom

示例

var str = '1234567899';
var str2 = '12345678999';
    
var reg = /^(?:([0-9])(?!\1{2})){1,}$/;

reg.test(str); // true
reg.test(str2); // false

上例中的效果是,匹配一个数字,但是数字中不允许连续出现3次以上的重复数字

  • 用到反向引用可以很好的实现

非捕获组

上述可以看到()包括的内容默认匹配时都在捕获组中

但是有时候,因为特殊原因用到了(),但又没有引用它的必要,这时候就可以用非捕获组声明,防止它作为捕获组,降低内存浪费

  • ?:可以声明一个子表达式为非捕获组
var str = 'abcd0123ABCD';
var reg = /(?:[a-z]+)(\d+)([A-Z]+)/g;

reg.test(str); // true

console.log(RegExp.$0); // undefined
console.log(RegExp.$1); // 0123
console.log(RegExp.$2); // ABCD

可以看到,(?:[a-z]+)将这个子表达式声明成了非捕获组,因此捕获组的编号直接跳过了它,从下一个(\d+)开始

.\s\S

首先说下.

  • 定义是除\n以外的任何字符
  • 但是,在一些ChromeFirefox等内核中,代表\n\r以外的字符
  • 如果要匹配.本身,请用\.

再说说\s\S

  • \s是匹配所有的空白字符,包括空白换行tab缩进等所有空白
  • \S是指除了空白以外的任何字符(和.区别下,.里面还多了一部分空白)

那如何匹配所有字符呢?

  • (.|\n)或者是[\s\S](推荐用法)
  • 请不要试图使用[.\n][\.\n],这种写法只表示小数点或\n字符中的一个

示例

请写一个表达式,去除多行注释

var str = '\
    var a = 1; \r\n\
    /\** \r\n\
    * 这里是注释 \r\n\
    */\r\n\
    var b = 2;\r\n\
    console.log(a)';

var reg = xxx;

str = str.replace(reg,'');

解答

var reg = /\/\*{1,}[\s\S]*\*\//g;

这里就用的了用[\s\S]来匹配所有的字符(因为仅仅是.是无法匹配\r\n的)

\b 单词边界

\b匹配单词边界,不匹配任何字符

简单的说,\b匹配的位置,一侧是构成单词的字符,另一侧是非单词字符,字符串的开始或结束

而其中单词的判断就是\w的匹配范围(正常a-zA-Z0-9_JS举例)

注,有一特例,在字符组中[\b]表示的是退格符

特点

  • 零宽,即匹配的是位置而不是字符
  • \w来界定单词
  • 字符组中是退格符的意思

示例

var str = 'abc_d=efg+hij哈opq%';
    
var reg = /.\b./g;

// ["d=","g+","j哈","q%"]
str.match(reg);

可以看到,分别在如下几处有单词分界

  • d=直接有一个分界
  • g+之间
  • j
  • q%

\转义

var str = 'ab\\cd'; // 字符串 ab\cd
var str2 = 'ab\\\\cd'; // 字符串 ab\\cd
    
var reg = /ab\\\\cd/;
var reg2 = new RegExp('ab\\\\cd');

reg.test(str); // false
reg.test(str2); // true

reg2.test(str); // true
reg2.test(str2); // false

出现\的地方,得多加注意,需要梳理清楚转义逻辑,通过上例可以看到,在正则中出现的\和在字符串中出现的\意义不一样

  • reg中,\出现在正则中,所以\\\\的意思就是匹配\\字符串,所以测试str2通过,str失败
  • reg2中,\出现在字符串中,所以\\\\的意思\\,然后构建为正则表达式,最终在正则中是\\,也就是匹配\字符串本身,所以测试str通过,str2失败

附录

博客

初次发布2017.07.31于个人博客

http://www.dailichun.com/2017/08/01/regularExpressionConcepts.html

参考资料

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


jquery.validate使用攻略(表单校验) 目录 jquery.validate使用攻略1 第一章&#160;jquery.validate使用攻略1 第二章&#160;jQuery.validate.js API7 Custom selectors7 Utilities8 Validato
/\s+/g和/\s/g的区别 正则表达式/\s+/g和/\s/g,目的均是找出目标字符串中的所有空白字符,但两者到底有什么区别呢? 我们先来看下面一个例子: let name = &#39;ye wen jun&#39;;let ans = name.replace(/\s/g, &#39;&#3
自整理几个jquery.Validate验证正则: 1. 只能输入数字和字母 /^[0-9a-zA-Z]*$/g jQuery.validator.addMethod(&quot;letters&quot;, function (value, element) { return this.optio
this.optional(element)的用法 this.optional(element)是jquery.validator.js表单验证框架中的一个函数,用于表单控件的值不为空时才触发验证。 简单来说,就是当表单控件值为空的时候不会进行表单校验,此函数会返回true,表示校验通过,当表单控件
jQuery.validate 表单动态验证 实际上jQuery.validate提供了动态校验的方法。而动态拼JSON串的方式是不支持动态校验的。牺牲jQuery.validate的性能优化可以实现(jQuery.validate的性能优化见图1.2 jQuery.validate源码 )。 也可
自定义验证之这能输入数字(包括小数 负数 ) &lt;script type=&quot;text/javascript&quot;&gt; function onlyNumber(obj){ //得到第一个字符是否为负号 var t = obj.value.charAt(0); //先把非数字的都
// 引入了外部的验证规则 import { validateAccountNumber } from &quot;@/utils/validate&quot;; validator.js /*是否合法IP地址*/ export function validateIP(rule, value,cal
VUE开发--表单验证(六十三) 一、常用验证方式 vue 中表单字段验证的写法和方式有多种,常用的验证方式有3种: data 中验证 表单内容: &lt;!-- 表单 --&gt; &lt;el-form ref=&quot;rulesForm&quot; :rules=&quot;formRul
正则表达式 座机的: 例子: 座机有效写法: 0316-8418331 (010)-67433539 (010)67433539 010-67433539 (0316)-8418331 (0316)8418331 正则表达式写法 0\d{2,3}-\d{7,8}|\(?0\d{2,3}[)-]?\d
var reg = /^0\.[1-9]{0,2}$/;var linka = 0.1;console.log (reg.test (linka)); 0到1两位小数正则 ^(0\.(0[1-9]|[1-9]{1,2}|[1-9]0)$)|^1$ 不含0、0.0、0.00 // 验证是否是[1-10
input最大长度限制问题 &lt;input type=&quot;text&quot; maxlength=&quot;5&quot; /&gt; //可以 &lt;input type=&quot;number&quot; maxlength=&quot;5&quot; /&gt; //没有效
js输入验证是否为空、是否为null、是否都是空格 目录 1.截头去尾 trim 2.截头去尾 会去掉开始和结束的空格,类似于trim 3.会去掉所有的空格,包括开始,结束,中间 1.截头去尾 trim str=str.trim(); // 强烈推荐 最常用、最实用 or $.trim(str);
正则表达式语法大全 字符串.match(正则):返回符合的字符串,若不满足返回null 字符串.search(正则):返回搜索到的位置,若非一个字符,则返回第一个字母的下标,若不匹配则返回-1 字符串.replace(正则,新的字符串):找到符合正则的内容并替换 正则.test(字符串):在字符串中
正整数正则表达式正数的正则表达式(包括0,小数保留两位): ^((0{1}.\d{1,2})|([1-9]\d.{1}\d{1,2})|([1-9]+\d)|0)$正数的正则表达式(不包括0,小数保留两位): ^((0{1}.\d{1,2})|([1-9]\d.{1}\d{1,2})|([1-9]+
JS 正则验证 test() /*用途:检查输入手机号码是否正确输入:s:字符串返回:如果通过验证返回true,否则返回false /function checkMobile(s){var regu =/[1][3][0-9]{9}$/;var re = new RegExp(regu);if (r
请输入保留两位小数的销售价的正则: /(^[1-9]([0-9]+)?(\.[0-9]{1,2})?$)|(^(0){1}$)|(^[0-9]\.[0-9]([0-9])?$)/ 1.只能输入英文 &lt;input type=&quot;text&quot; onkeyup=&quot;value
判断价格的正则表达式 价格的正则表达式 /(^[1-9]\d*(\.\d{1,2})?$)|(^0(\.\d{1,2})?$)/; 1 解析:价格符合两种格式 ^ [1-9]\d*(.\d{1,2})?$ : 1-9 开头,后跟是 0-9,可以跟小数点,但小数点后要带上 1-2 位小数,类似 2,2
文章浏览阅读106次。这篇文章主要介绍了最实用的正则表达式整理,比如校验邮箱的正则,号码相关,数字相关等等,本文给大家列举的比较多,需要的朋友可以参考下。_/^(?:[1-9]d*)$/ 手机号
文章浏览阅读1.2k次。4、匹配中的==、an==、== an9、i9 == "9i"和99p==请注意下面这部分的作用,它在匹配中间内容的时候排除了说明:当html字符串如下时,可以匹配到两处,表示匹配的字符串不包含and且不包含空白字符。说明:在上面的正则表达式中,_gvim正则表达式匹配不包含某个字符串
文章浏览阅读897次。【代码】正则表达式匹配a标签的href。_auto.js 正则匹配herf