JavaScript-的RegExp类型详解

正则表达式包含原意文本字符和元字符(即正则表达式中有特殊含义的非字母字符*+?$^.|[](){}等)

  • 元字符包含:
    • \t:水平制表符
    • \v:垂直制表符
    • \n:换行符
    • \0:空白符
    • \f:换页符
    • \cX:与X对应的控制字符 (Ctrl+X)

下面我们来介绍正则中的各种类型及操作方法

Ⅰ.字符类

  • 一般情况下正则表达式一个字政府对应字符串的一个字符
  • 可使用“[]”构建一个简单的类(符合某些特征的对象,泛指)
    • eg”:
'a1b2c3d4'.replace(/[abc]/g, 'X')

=>X1X2X3X4
  • 取反:[^abc]

Ⅱ.范围类

  • 如[a-z]表示从a到z的任意字符
    • eg:[a-zA-Z]表示大小写完全匹配
    • eg:
'2018-5-23'.replace(/[0-9-]/g, 'A');
=>AAAAAAAAA

Ⅲ.预定义类

字符等价类作用
.[^\r\n]除回车、换行
\d[0-9]数字
\D[^0-9]非数字
\s[\t\n\xB\f\r]空白符
\S[^\t\n\xB\f\r]非空白符
\w[a-zA-Z_0-9]单词字符(包括下划线)
\W[^a-zA-Z_0-9]非单词字符

- 边界

符号意义
^以xxx开始
$以xxx结束
\b单词边界
\B非单词边界

有点不太明朗对吧,咱们举几个例子

str = 'This is a boy';
str.replace(/\bis\b/g, '0');
//This 0 a boy

str.replace(/\Bis\b/g, '0');
//Th0 is a boy

str = '@123@abc@';
str.replace(/@./g, 'Q');
<!--  Q23Qbc@  -->

str.replace(/^@./g, 'Q');
<!-- Q23@abc@ -->

str.replace(/.@$/g, 'Q');
<!-- @123@abQ -->

mulSrt = "
    @123
    @456
    @789
"
mulSrt.replace(/^@\d/gm, 'X');
<!--  m代表多行匹配  -->
<!--  X23  -->
<!--  X56  -->
<!--  X89  -->

Ⅳ.量词

符号意义
?最多出现一次
+至少出现一次
*任意次
{n}出现n次
{n,m}出现n到m次
{n,}至少出现n次

这个好理解

\d{3}:匹配3次数字

Ⅴ.贪婪模式

顾名思义,在范围内尽可能多的匹配
eg:

'12345678'.replace(/\d{3,6}/g, 'X');    //X78

非贪婪模式

'123456789'.match(/\d{3,5}?/g);  //["123","456","789"]
'12345678'.replace(/\d{3,6}?/g, 'X');   //XX78

Ⅵ.分组

由于量词只能作用域其紧挨着的单词,故我们需用“()”分组

'a1b2bc3d4'.replace(/([a-z]\d){3}/g .'X');
'ByronsperByrCasper'.replace(/By(on|Ca)sper/g, 'X');    //XX

反向引用:用“$”捕获分组

'2018-05-20'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$2/$3/$1');   //05/20/2018

<!-- 不希望捕获分组的话,只需要在分组内加上“?:” -->
eg:(?:Byron)

Ⅶ.前瞻&&后顾

前瞻:在正则表达式匹配到规则的时候,向前检查是否符合断言
后顾则方向相反

但是JavaScript不支持后顾,咱们就不说拉

正向前瞻:exp(?=assert)
负向前瞻:exp(?!assert)

'a2*3'.replace(/w(?=\d)/g, 'X');    //X2*3

Ⅷ.对象属性

  • global:是否全局搜索,默认false
  • ignoreCase:是否大小写敏感,默认false
  • multiline:多行搜索,默认false
  • lastIndex:是当前表达式匹配内容的最后一个字符的下一个位置
  • source:正则表达式的文本字符串
var reg1 = /\w/;
reg1.source;        //'\w'

test和exec方法

RegExp.prototype.test(str);

用于测试字符串参数中是否存在匹配正则表达式的字符串(返回一个boolean)
eg

var reg1 = /\w/g; 

reg1.test('ab');        //true
reg1.test('ab');        //true
reg1.test('ab');        //false
reg1.test('ab');        //true
reg1.test('ab');        //true
reg1.test('ab');        //false

为什么会出现这种情况呢?因为若带上全局搜索g的话会影响lastIndex的值
我们不妨写一段代码进行测试

while(reg1.test('ab')){
    console.log(reg1.lastIndex);
}

<!-- 1 2 -->

RegExp.prototype.exec(str)

  • 使用正则表达式模式对字符串进行搜索,并将更新全局RegExp对象的属性以及反应匹配结果。未匹配到返回null。否则返回一个结果数组
    • index生命匹配文本的第一个字符的位置
    • input存放呗检索的字符串string

1.非全局调用

var reg1 = /\d(\w)\d/;
var reg2 = /\d(\w)\d/g;

var ts = "$1a3b3c4d5e";

var ret = reg1.exec(ts);
console.log(reg1.lastIndex + '\t' +ret.index + '\t' + ret.toString());  
//0  1  1a2,a

2.全局调用

while(ret = reg2.exec(ts)){
    console.log(reg1.lastIndex + '\t' +ret.index + '\t' + ret.toString();
}
//4  1  1a2,a
//8  5  3c4,c

字符串对象方法

  • String.prototype.search(reg)
    • 用以检索字符串中制定的子字符串,或检索与正则表达式相匹配的子字符串(找不到返回-1,找到返回第一个的index。忽略g标志)
  • String.prototype.match(reg)
    • 检索字符串,找到一个或多个与regexp匹配的文本(返回数组或Null)
  • String.prototype.split(reg);
    • 分割
  • String.prototype.replace(reg,function)
"a1b2c3d4e5".replace(/\d/g, function(match, index, orign){
    //match为匹配到的结果
    console.log(index);
    return parseInt(match)+1;
});

//a2b3c4d5e6