JS中的正则表达式(一)

正则表达式的定义

正则表达式是具有特殊语法的字符串,用来表示制定字符或字符串在另一个字符串中出现的情况。可以实现很多功能如验证手机号码、验证日期、验证银行卡号等。

定义:
(1) 对象定义法 即使用RegExp构造函数进行定义
var reg1 = new RegExp(“表达式”);
var reg1 = new RegExp(“表达式”,“i”); // 第二个参数表述匹配时不区分大小写
RegExp构造函数第一个参数为正则表达式的文本内容,而第二个参数则为可选项标志.标志可以组合使用
•g (全文查找)
•i (忽略大小写)
•m (多行查找)

var re = new RegExp("a","gi");//匹配所有的a或A  

正则表达式还有另一种正则表达式字面量的声明方式

(2) 字面量
var reg2 = /表达式/;
定义好正则表达式后要做的可能是判断某个字符串是否匹配制定的模式。

使用RegExp对象的方法

这个可以先忽略掉,等你看完全篇的时候再来看这些方法,会有一种豁然开朗的感觉,因为写这段的时候,我是先写完后面的又补充的。

  1. test()方法 :如果给定字符串(只有一个参数)匹配这个模式,它就会返回true,否则返回false。
var str = "cat";
var reCat =/cat/;
console.log(reCat.test(str)); // true
  1. exec()方法,有一个字符串参数,返回一个数组。数组中的第一个条目是第一个匹配;其他的是反向引用。
var str1 = "a bat, a Cat. a fat baT, a faT cat";
var reAt = /at/;
var arr = reAt.exec(str1);
console.log(arr);//["at", index: 3, input: "a bat, a Cat. a fat baT, a faT cat"]

这里arr 只包含一个条目,第一个at 的实例(在单词bat中的那个)。但是为什么这样只能返回一个条目的数组呢,假设想要获得某个模式的所有出现呢?这里需要用match()方法

  1. match()方法,它会返回一个包含字符串中的所有匹配的数组,这个方法调用string对象,同时传给它一个RegExp对象。
var str1 = "a bat, a Cat. a fat baT, a faT cat";
var reAT=/at/gi;
var arrAt =str1.match(reAT);
console.log(arrAt); //["at", "at", "at", "aT", "aT", "at"]
  1. search()方法 这个字符串方法的行为与indexOf()有些类似,但是它使用一个RegExp对象而非仅仅一个字符串。search()方法返回在字符串中出现的一个匹配的位置。
var str2 ="a bat, a Cat. a fat baT, a faT cat";
var reA =/at/gi;
console.log(str2.search(reA)); // 3
  1. replace()方法 它可以用另一个字符串(第二个参数)来替换某个子串(第一个参数)的所有匹配。
var sChange ="The sky is red.";
console.log(sChange.replace("red","blue"));//The sky is blue.

子字符串red被字符串blue替换,最终输出The sky is blue.也可以给第一个参数传递一个正则表达式

var sChange ="The sky is red.";
var reRed =/red/;
var sResult = sChange.replace(reRed,function (sMatch) {
    return "blue";
});
console.log(sResult); //The sky is blue.
  1. split()方法,可以将字符串分割成一系列子串并通过一个数组将它们返回。
var sColor ="red,blue,yellow,green";
var arrColors =sColor.split(",");

//使用正则表达式也可实现同样的功能
var reComma =/\,/;
var arrColorsReg = sColor.split(reComma);
console.log(arrColorsReg);//["red", "blue", "yellow", "green"]

正则表达是的组成

元字符、字符类和量词等都是正则表达式中重要的组成部分。
元字符是具有特殊意义的字符,这里我们列举正则表达式用到的所有的元字符:
( [ { \ ^ $ | } ? * + .
正则表达式要使用这些元字符,都必须对它们进行转义。举个例子,要匹配一个问号? 正则表达式应该这样表示
var reQ1 = /\?/;
如果构造函数的形式使用元字符时,表达式中所有的反斜杠必须用两个反斜杠来替换,因为JavaScript字符串解析器会按照翻译\n 的方式尝试翻译\? 为了保证不出现这个问题,在元字符的前面加上两个反斜杠\,称之为双重转义。
var reQ2 = new RegExp(“\?”)
双重转义这么不友好,所以还是用正则表达式字面量的声明方式

字符类:

字符类是用于测试的字符组合。将一些字符放在方括号中,可以很有效的告诉正则表达式去匹配第一个字符、第二个字符等等。
“[ab]”:表示一个字符串有一个”a”或”b”(相当于”a¦b”);
字符类包含:简单类,反向类,范围类,组合类,预定义类

  1. 简单类(simple class )
    通俗的讲就是在正则表达式中// 什么特殊符号都不写,直接放到[]中去。现在用火眼金睛去发现一些问题:
console.log(/sweet/.test("sweet")); //true
console.log(/sweet/.test("sweety")); //true
console.log(/sweet/.test("sw")); //false
console.log(/sweet/.test("t")); //false
console.log(/[sweet]/.test("swe")); // true
console.log(/[sweet]/.test("sw")); // true
console.log(/[sweet]/.test("t")); // true

我们会发现 带[]的 只要匹配其中的任何一个就返回true 。如果正则表达式sweet不带[] 如果返回true就要匹配完整 sweet或者比sweet多的字符,否则false。

  1. 负向类 negation class
    负向类可以指定要排除的字符。 例如要匹配除了a和b的所有字符,那么这个字符类就是[^ab]. 脱字符号(^)告诉正则表达式字符不能匹配后面跟着的字符。 注意:这个^一定要写到方括号里面。在方括号中,不需要转义字符。
var  str = "andy";
var strM = /[^ab]/;
console.log(strM.test(str));// true
console.log(/[^abc]/.test('a')); //false
console.log(/[^abc]/.test('ab'));//false
console.log(/[^abc]/.test('abg'));//true
console.log(/[^abc]/.test('gg')); //true

总结一下吧:
中括号前面加个元字符^进行取反。如果要匹配的字符不够或者正好与正则表达式相等,返回false。 多了其他的字符或者原本就是其他的字符就返回 true。

  1. 范围类 range class
    如果想匹配所有的字母或者数字,不想逐个输入,可以使用范围类。比如a到z之间的范围[a-z] 0到9 [0-9]重点是那条横线-
console.log(/[0-9]/.test('9ag')); //true
console.log(/[a-z]/.test('999')); //false
console.log(/[A-Z]/.test('ahga')); //false
console.log(/[A-Z]/i.test('ahga')); // true

要想不区分大小写 正则表达式用i来指明
4. 组合类 combination class
组合类是由几种其他的类组合而成的字符类。
例如要匹配所用的从a 到m的字母以及1到5的数字,以及一个换行符,那么所用到的类应该这样:
[a-m1-5\n]
注意:
1).在内部的类之间不要有空格。
2). js和es不支持某些正则表达式中的联合类和交叉类。这意味着你不能有类似[a-m[p-z]]或者[a-m[^b-f]]之类的模式出现。

console.log(/[a-m1-5]/.test("4"))//true
console.log(/[a-m1-5]/.test("d4"))//true
console.log(/[a-m1-5]/.test("n5"))//true
console.log(/[a-m1-5]/.test("y9"))//false
  1. 预定义类
    可以用一组预定义字符类让我们更方便地指定复杂类
    . [^\n\r] 除了换行和回车之外的任意字符(“”不行)
    \d [0-9] 数字字符
    \D [^0-9] 非数字字符

    \s [ \t\n\x0B\f\r] 空白字符
    \S [^ \t\n\x0B\f\r] 非空白字符

    \w [a-zA-Z_0-9] 单词字符
    \W [^a-zA-Z_0-9] 非单词字

console.log(/./.test("\n\r"));  //false
console.log(/./.test("adsfadsgdfgdfg"));// true
console.log(/\d/.test(123)); //true
console.log(/\d/.test("adsfadsgdfgdfg")); //false
console.log(/\s/.test("     ")); // true
console.log(/\s/.test("asdfadsf"));//false
console.log(/\w/.test("$")); //false
console.log(/\w/.test("_")); // true
var str = "567 897 abc";
var strM = /[0-9][0-9][0-9]/;
console.log(strM.test(str)); // true

var strMs = /\d\d\d/;
console.log(strMs.test(str));//true

量词quantifier

量词可以指定某个特定模式出现的次数。
1.简单量词
?:出现零次或一次
*:出现零次或多次(任意次)
+:出现一次或多次(至少出现一次)
{n}:一定出现n次
{n,m}:至少出现n次但不超过m次
{n,}:至少出现n次
var str = /b?rea?d/; 可以这样理解: b出现零次或一次,跟着r,跟着e,跟着出现零次或一次的a,跟着d。
也可以写成这个样子
var str =/b{0,1}rea{0,1}d/;

console.log(/b?rea?d/.test("abcd")); //false
console.log(/b?rea?d/.test("ba")); //false
console.log(/ba?d/.test("ba")); // false
console.log(/[b?rea?d]/.test("abcd")); //true
console.log(/[b?rea?d]/.test("ba")); //true
console.log(/[ba?d]/.test("ba")); // true

怎样表示贪婪、惰性和支配性量词呢?正是完全使用星号*、加号+和问号?
例如: 单独使用一个问号(?)是贪婪的,但是问号后面在跟一个问号(??)就是惰性的。要使问号成为支配量词,在后面加上一个加号(?+)

  • 用贪婪量词进行匹配时,它首先会将整会字符串当成一个匹配,如果匹配的话就退出,如果不匹配,就截去最后一个字符进行匹配,如果不匹配,继续将最后一个字符截去进行匹配,直到有匹配为止。直到现在我们遇到的量词都是贪婪量词
  • 用惰性量词进行匹配时,它首先将第一个字符当成一个匹配,如果成功则退出,如果失败,则测试前两个字符,依些增加,直到遇到合适的匹配为止

惰性量词仅仅在贪婪量词后面加个”?”而已,如”a+”是贪婪匹配的,”a+?”则是惰性的

var str = "abc";  
var re = /\w+/;//将匹配abc  
re = /\w+?/;//将匹配a 

正则表达式的边界:

^ 会匹配行或者字符串的起始位置
注:^在[]中才表示非!这里表示开始
会匹配行或字符串的结尾位置  
^
在一起 表示必须是这个(精确匹配)

// 边界可以精确说明要什么
console.log(/lily/.test("lilyname")); // true
console.log(/^lily$/.test("lily"));  // true
console.log(/^lily$/.test("ly"));   // false
console.log(/^sweet$/.test("sweety")); //false

console.log(/^sweet$/.test("sweet"));  // true
这个的最终意思就是 说, 必须是 sweet 这四个字母

复杂模式

  1. 分组
    分组是通过一系列括号包围一系列字符、字符类以及量词来使用。
    例如:var reCatCat = /catcat/g;
    这样写有点浪费,如果不知道cat字符在字符串中出现几次时,可以用分组来重写这个表达式 var reCatCat = /(cat){2}/g;
    表达式中的() 意思是 字符“cat”将在一行上连续出现两次,但是并不限制在分组后使用花括号{},可以使用任意量词。

  2. 反向引用: (针对分组)
    每个分组都被放在一个特殊的地方以备将来使用。这些存储在分组中的特殊值,我们称之为反向引用(backreference)。
    反向引用是按照从左到右遇到的左括号字符的顺序进行创建和编号的。

var re = /(A?(B?(C?)))/;
/*上面的正则表达式将依次产生三个分组
 (A?(B?(C?))) 最外面的
 (B?(C?))
 (C?)*/
str = "ABC";
re.test(str);//反向引用被存储在RegExp对象的静态属性1—9中
console.log(RegExp.$1+"\n"+RegExp.$2+"\n"+RegExp.$3); // ABC BC C
//RegExp.$1  ==>ABC    RegExp.$2==>BC   RegExp.$3===>C

//反向引用也可以在正则表达式中使用\1 ,\2...这类的形式使用
re = /\d+(\D)\d+\1\d+/;    // 这里的\1  指的是(\D)
str = "2008-1-1";
console.log(re.test(str));//true
str = "2008-4_3";
console.log(re.test(str));//false
再来个例子强调一遍:var sToMatch = “dogdog”;
var reDogDog = /(dog)\1/;
console.log(reDogDog.test(sToMatch)); // true
重新 解释一下: 正则表达式reDogDog 首先创建dog的分组,然后又被特殊转义序列\1引用,使得这个正则表达式等同于 /dogdog/ .(个人理解  \1  指的就是分组的dog)

  1. 候选(简单理解为 “或|”)
var str1 = "cat";
var str2 ="dog";
var reCat = /cat/;
var reDog =/dog/;

//正则表达式可以写成
var reg = /cat|dog/;

console.log(reg.test(str1));
console.log(reg.test(str2));
re = /^c|mn$/;//将匹配开始位置的c或结束位置的mn
str ="cat";
console.log(re.test(str));//true
re = /^(c|mn)$/;//将匹配c或mn
str ="bc";
str2 ="mn";
console.log(re.test(str));//false
console.log(re.test(str2));//true
  1. 非捕获性分组
    不会创建反向引用。创建一个非捕获性分组,只要在左括号的后面加上一个问号(?)和一个紧跟的冒号(:)
var str ="#123456789";
var reg=/#(?:\d+)/;
console.log(reg.test(str)); // true
console.log(RegExp.$1);  // 输出为 ""

最后一行代码输出一个空字串,因为该分组是非捕获性的,所以不能通过RegExp.$1变量来使用任何反向引用。

  1. 前瞻
    它告诉正则表达式运算器向前看一些字符而不移动其位置。 前瞻分为正向前瞻和负向前瞻。正向前瞻检查的是接下来出现的是不是某个特定字符集。负向前瞻则是检查接下来的不应该出现的特定字符集。
    创建正向前瞻要将模式放在(?=和)之间。注意:这个不是分组,虽然也用到了括号,事实上,分组不会考虑前瞻的存在(无论正向的还是负向的)。
var str1 ="bedroom";
var str2 ="bedding";
var reBed =/(bed(?=room))/;
console.log(reBed.test(str1));  //true
console.log(RegExp.$1); // bed
console.log(reBed.test(str2)); //false

这个例子,reBed只匹配后面跟着room 的bed ,故只能匹配str1 而不能匹配str2 。
注意: RegExp.$1 的内容是bed ,而不是bedroom 。模式的room部分是包含在前瞻中的,所以没有作为分组的一部分。
负向前瞻 :是要将模式放在(?!和)之间

var str1 ="bedroom";
var str2 ="bedding";
var reBed =/(bed(?!room))/;
console.log(reBed.test(str1));  //false
console.log(RegExp.$1); // bed
console.log(reBed.test(str2)); //true

这里表达式只匹配后面不跟着room的bed 。 RegExp.$1 的内容仍是bed。
6. 多行模式:在正则表达式后面添加一个 m 选项

var str ="First second\nthird fourth\nfifth sixth";
var reg = /(\w+)$/g;
console.log(str.match(reg)); //["sixth"]

这代码想要匹配行末的一个单词,匹配的是“sixth” ,因为只有它在字符串的结尾处。但是,str中有两个换行符,所以 second fourth也应该返回,这就是引入多行模式的原因。
要指定多行模式,只要在正则表达式后面添加一个m选项,这会让$边界匹配换行符\n 以及字符串真正的结尾。

var regE = /(\w+)$/gm;
console.log(str.match(regE)); //["second", "fourth", "sixth"]

多行模式同样也会改变^边界的行为,这时它会匹配换行符之后的位置,
var regEStart = /^(\w+)/gm;
console.log(str.match(regEStart));// ["First", "third", "fifth"]

写的有点啰嗦 ,本来看正则表达式看的一头雾水的,多看几遍就会有不同的见解。也就全都写下来,省的以后忘了。不喜勿喷!这仅仅是我的学习笔记而已!

你可能感兴趣的:(JS基础知识整理)