5、正则表达式

2017-07-24  本文已影响0人  Elevens_regret

正则的解释

正则表达式的创建

// 两个正斜杠定义正则字面量的边界
var reg = /test/;
// 构造RegExp实例
var reg = new RegExp("test");

3个匹配标志的使用方法

// i 表示不区分大小写
// g 表示全局匹配,而不是只匹配第一次出现的结果
// m 表示允许多行匹配
var reg = /test/igm;
var reg = new RegExp("test","igm");

正则的术语与操作符

匹配一个有限字符集中的某一个字符

// 表示匹配a,b,c中的任意一个字符
var reg = /[abc]/;

在中括号第一个括号后面加入^,表示匹配该组有限字符集以外的字符

// 表示匹配除了a,b,c以外的任意字符
var reg = /[^abc]/;

在字符集之间加入-,表示制定一个范围

// 表示匹配a到m之间的任意字符,包括a和m
var reg = /[a-m]/;

转义,在正则表达式中,字母和数字都能代表自己本身,但类似$-.[]等特殊字符都有其他含义,要匹配这些字符,需要用\对其进行转义

// 表示匹配$字符
var reg = /\$/;

匹配的开始与结束

当^作为正则表达式的第一个字符时,表示必须从字符串的开头进行匹配。

// 表示匹配以abc开头的字符串
var reg = /^abc/;

当$作为正则表达式的最后一个字符时,表示该模式必须出现在字符串的结尾。

// 表示匹配以abc结尾的字符串
var reg = /abc$/;

同时使用^和$时,表示匹配模式必须包含整个字符串,即匹配模式就是字符串本身,没有任何其他字符。

// 表示匹配"abc"这个字符串,"abcabc"之类的不会匹配
var reg = /^abc$/;

重复出现

在一个字符后面加一个?,表示该字符是可选的,也就是可以出现一次或不出现

// 表示匹配abc或者bc,
var reg = /a?bc/;

在一个字符后面加一个+,表示该字符可以出现一次或多次

// 表示匹配abc或者aaabc,
var reg = /a+bc/;

在一个字符后面加一个*,表示该字符可以出现零次或多次,即任意次数

// 表示匹配abc或者aaabc或者bc,
var reg = /a*bc/;

在字符后跟花括号,在起重指定一个数字,表示该字符出现的次数

// 表示匹配aaaa,
var reg = /a{4}/;

在字符后跟花括号,在起重指定一个区间,表示该字符出现的次数区间

// 表示匹配a出现次数在4到10之间任意次数的字符串,包括4次和10次
var reg = /a{4,10}/;

次数区间第二个数值是可选的,当没有第二个数字是,表示匹配一个开区间

// 表示匹配a出现次数至少4次
var reg = /a{4,}/;

以上重复操作符可以是贪婪的或者非贪婪的,默认情况下是贪婪的,表示尽可能多的匹配,例如,匹配"aaa"字符串时,/a+/模式将匹配所有3个a。在操作符后面加上?,表示非贪婪模式,将进行最小限度的匹配,匹配"aaa"字符串时,/a+?/模式只会匹配一个a字符。因为一个a字符就满足+表示的一次或多次的情况。

预定义字符类

\t  水平制表符
\b  空格
\n  换行符
.   匹配除换行以外的任意字符
\d  匹配任意数字,等价于[0-9]
\D  匹配任意非数字,等价于[^0-9]
\w  匹配包括下划线的任意单词字符,等价于[A-Za-z0-9_]
\W  匹配任何非单词字符,等价于[^A-Za-z0-9_]
\s  匹配任何空白符,包括空格,制表符,换页符等
\S  匹配任何非空白字符
\b  匹配单词边界
\B  匹配非单词边界

分组

在为匹配模式加上小括号,可以让其成为一个分组,后续添加的操作符可以影响整个分组。

// 表示匹配出现一次或连续多次的ab字符串,例如"xxxabxxx","xxxabababxxx"
var reg = /(ab)+/;

或操作符

竖线|表示或操作符

// 表示匹配a或b
var reg = /a|b/;
// 表示匹配出现一次或多次的"ab"或"ba"
var reg = /(ab)+|(ba)+/;

反向引用

反斜杠后面加一个数字表示要引用之前已经匹配到的分组

// \1表示再匹配一次第一个分组([ab])匹配到的内容,\2表示再匹配一次第二个分组(a)匹配到的内容。
// 并且不是再次对分组中的模式进行匹配,而是对已经匹配到的一模一样的内容进行精确匹配。
// 例如第一个分组([ab])匹配到了字符b,\1匹配的就也必须是字符b
var reg = /([ab])(a)\1\2/;

反向引用常用来匹配元素的标签

// \1表示对第一个分组(\w+)匹配到的内容再次匹配,内容必须完全相同。因为标签的开始和关闭是相同的。
var reg =/<(\w+)>.*<\/\1>/;
var a = "<strong>some thing</strong>";
console.log(reg.test(a)); // true

正则表达式的编译

正则表达式的编译发生在第一次被创建的时候,而执行则是发生在我们使用编译过的正则表达式进行字符串匹配的时候。所以正则表达式只应该编译一次,并将其保存在一个变量中以供后续使用,这是一个重要的优化过程。每次创建的正则表达式都是一个新的对象,其结果都是独一无二的。
使用构造器(new RegExp())可以通过动态的字符串创建正则表达式。

捕获匹配的片段

匹配到的内容中,每一个括号分组都是一个片段,使用字符串的match()方法可以捕获匹配的片段。
在非全局匹配时。其返回结果是一个数组,第一个索引的值是该匹配的完整结果,之后的参数是每一个捕获的片段。
在全局匹配时。其返回结果也是一个数组,但数组的值是所有的匹配结果,每一个匹配结果的捕获片段是不会返回的。

// 非全局匹配
var reg =/<(\w+)([^>]*)>/;
var a = '<div class="abc">hello</div>';
var b = a.match(reg);
console.log(b); // ["<div class="abc">", "div", " class="abc""]
// 全局匹配
var reg =/(\w+)([^>]*)>/g;
var a = '<div class="abc">hello</div>';
var b = a.match(reg);
console.log(b); // ["div class="abc">", "hello</div>"]

正则表达式的exec()方法,可以对同一个字符串进行多次匹配,每一次匹配都会返回下一个匹配的结果

var reg =/<(\w+)([^>]*)>/g;
var a = '<div class="abc"><p>hello <span>world</span></p></div>';
var b = reg.exec(a);
var c = reg.exec(a);
var d = reg.exec(a);
console.log(b); // ["<div class="abc">"]
console.log(c); // ["<p>"]
console.log(d); // ["<span>"]

捕获的引用

在replace()方法中,可以使用$1,$2,$3这样的语法来引用之前捕获到的分组。

// 正则中的$1表示第一个捕获到的分组中的内容,即[A-Z]匹配到的内容。
var a = 'borderColor';
var b = a.replace(/([A-Z])/g,"-$1").toLowerCase();
console.log(b); // border-color

没有捕获的分组

在分组的左括号后加一个?:标记,表示这个分组不需要被捕获。

var reg = /(?:-[A-Z])/;
var a = 'border-Color';
var b = a.match(reg);
// 只返回了匹配的内容,没有返回分组中的内容
console.log(b[1]);  // undefined

在不需要捕获的时候,尽量可能的使用非捕获分组,减少引擎的工作量。

利用函数进行替换

replece()方法的第二个参数可以传入一个函数,全局模式下每个匹配都会调用这个函数,该函数有一个参数列表,分别为:

  1. 匹配的完整文本
  2. 匹配的捕获,一个捕获对应一个参数
  3. 匹配字符在元字符串中的索引
  4. 源字符串
function up(all,str) {
    return "-"+str.toLowerCase();
}
var a = 'borderBottomColor';
var b = a.replace(/([A-Z])/g,up);
console.log(b);  // border-bottom-color

利用这一特性可以修改一些数据的格式,例如将"a=1&a=2&a=3&b=4&b=5"修改为"a=1,2,3&b=4,5"。

function up(str) {
    var keys = {}; // 保存数据

    str.replace(/([^=&]+)=([^&]+)/g,function (all, key, value) {
        keys[key]=keys[key]?keys[key]+","+value:value;
    });

    var result = [];
    for (var key in keys){
        result.push(key+"="+keys[key]);
    }
    return result.join("&");
}
var a = 'a=1&a=2&a=3&b=4&b=5';
console.log(up(a));  // a=1,2,3&b=4,5

常见问题

// 删除前后空格,低端浏览器不支持trim()方法
var a = ' abc abc ';
console.log(a.replace(/^\s+|\s+$/g,""));  // abc abc
// 匹配换行符,/[\S\s]*/ 表示匹配所有字符
var a = 'abc\nabc';
console.log(/[\S\s]*/.exec(a)[0]); 
// 匹配Unicode
var a = '\u5FCD\u8005\u30D1\u30EF\u30FC';
console.log(a.match(/[\w\u0080-\uFFFF_-]+/)[0]);  // 忍者パワー
上一篇 下一篇

猜你喜欢

热点阅读