JavaScript——正则表达式

一直以来都没有太把正则表达式当回事,两次面试被问及时回答的都是需要用的时候百度。总觉得这很不对,所以学习并总结一遍。 正则表达式的字面量表示 var ex

一直以来都没有太把正则表达式当回事,两次面试被问及时回答的都是需要用的时候百度。总觉得这很不对,所以学习并总结一遍。

 

正则表达式的字面量表示

var expression = /pattern/flags;

flags

g—全局匹配

i—不区分大小写

m—多行模式

 

字符边界

有时需要确认一个模式是以特定的字符开头或结束的。

^ 匹配字符的开头,$ 匹配字符的结尾

/^a/.test('abcde'); // true
/^a$/.test('abcde'); // false
/^a$/.test('a'); // true

转义字符 \b 也可以匹配“字符边界”,它与 (^,$) 有些类似,只不过 \b 除了可以匹配开头和结尾,还可以匹配空格与标点。

/\bxyx\b/.test('abc,xyx,def'); // true

 

范围查找

如果需要匹配某个区间内的字符可以使用 [] 符号

[0-9] 匹配 0 到 9 之间的数字

[a-z] 匹配 a 到 z 之间的字符

[A-Z] 匹配 A 到 Z 之间的字符

[A-z] 匹配 A 到 z 之间的字符(大写在小写之前应该是大写字母的ASCII码值小吧)

[adksgd] 匹配其实任意一个字符

var reg = /[adksgd]/;
reg.test('as'); // true

 

重复模式

给元素后面加上重复符号表示重复匹配若干次

(*) 匹配任意次数(包括零次)

(+) 至少匹配一次

(?) 表示可选(一次或零次)

需要指定次数可以使用 {n,m}。

{n} 匹配 n 次

{n,m} 匹配 n-m次

{n,} 最少出现 n 次

{,m} 最多出现m次

 

子表达式分组

在同一表达式里,需要对多个字符使用 * 或 + 这样的特殊字符。可以使用小括号进行分组。

var minionsSay = /ba(na)+/i;
minionsSay.test('Banananananana!'); // true

 

多选一

使用 (|) 表示允许模式在多个元素中选择一个。

var sayColor = /\bcolor is (red|blue|yellow)\b/;
sayColor.test('color is blue'); // true

 

常用的元字符

(.) 用来表示“任何不是换行符的字符”

(\d) 表示“任意数字”

(\w) 匹配任何单词(任何英文、数字、下划线构成的字符)

(\s) 匹配任何空字符(Tab、换行和空格等)

(\b) 匹配单词边界

 

反模式

对元字符中的字母进行大写就可以实现反模式

(\D) 匹配非数字字符

(\W) 匹配非单词字符

(\S) 匹配任何非空字符

(\D) 匹配非单词边界

[^xxx] 匹配非中括号中的内容,只要出现其中一个字符即匹配失败

 

方法汇总

有关正则表达式的方法,有些是绑定正则实例上,有些是绑定在字符串本身上。

正则表达式方法:

test

检索字符串是否符合正则规范,返回布尔值。

var reg = /^a$/i;
var result = reg.test('A');
console.log(result); // true

exec

检索字符串中指定的值,返回匹配的值,并指定所在的位置。

var test = 'A, B, C, D, E';
var result = /\bc\b/i.exec(test);
console.log(result); // ["C", index: 6, input: "A, B, C, D, E"]

result 的第1项为匹配到的字符串,index 属性表示匹配到的位置,input 属性表示应用匹配的字符串。如果匹配失败,result 值为 null;

需要注意的是,如果对同一字符串调用 exec 方法,申明了全局模式 (g)的话每次开始匹配的位置都在上一次匹配结束的位置,反之从头开始匹配。

var text = 'cat, bat, sat, fat',
    pattern1 = /.at/,
    result = pattern1.exec(text);
console.log(result); //["cat", index: 0, input: "cat, bat, sat, fat"]
        
result = pattern1.exec(text);
console.log(result); //["cat", index: 0, input: "cat, bat, sat, fat"]

var pattern2 = /.at/g;
result = pattern2.exec(text);
console.log(result); //["cat", index: 0, input: "cat, bat, sat, fat"]

result = pattern2.exec(text);
console.log(result); //["bat", index: 5, input: "cat, bat, sat, fat"]

 

exec 方法同时也会匹配子模式的字符串,并按顺序存入数组中。下例为对美式日期进行格式化的一个函数。

function formatDate(string) {
  var result = /\b(\d+)\/(\d+)\/(\d{4})\b/.exec(string);
  if (result == null) {
    return;
  }
  console.log(result); // ["8/6/2016", "8", "6", "2016", index: 0, input: "8/6/2016"]
  var date = new Date(Number(result[3]), Number(result[2]), Number(result[1]));
  date = date.getFullYear() + '-' + date.getMonth() + '-' + date.getDate();
  return date;
  }

console.log(formatDate('8/6/2016')); // 2016-6-8

字符串方法:

search

检索并返回匹配字符所在字符串的位置索引值,与 indexOf 方法相似,只是接收的参数为正则实例对象。

var index = 'doubleKill'.search(/ek/i);
console.log(index); // 5

match

与上文中的 exec 方法很相似,只不过 exec 方法在正则对象上,而 match 方法在字符串上。

返回值也相同。

replace

将匹配正则的字符部分进行替换,要注意的是若没有申明全局模式 (g),只会替换第一个匹配的字符。

var reg = /a(b|c)/g,
    str = 'abDDacDD';
var result = str.replace(reg, 'A');
console.log(result); // ADDADD

replace 方法与正则相配合可以实现许多强大的功能,同时 replace 方法的第二个参数可以是函数,函数return的值即为替换后的值。

var text = 'The sun and the moon',
    result = text.replace(/\b(sun|moon)\b/g, function(str) {
        return str.toUpperCase();
    });
console.log(result); // The SUN and the MOON 

我们使用该方法来编写一个对输入字符转义,防范XSS的函数

function (text) {
  var replacements = {
      '<': '&lt;',
      '>': '&gt;',
      '&': '$amp;',
      '\"': '&quot'
  };
  return text.replace(/[<>&"]/g, function(str) {
    return replacements[str];
  });
}

 

构造函数模式

除了字面量形式的正则表达式,还可能通过 RegExp 构造函数的方法创建。

var pattern1 = /[bc]at/i;
var pattern2 = new RegExp('[bc]at','i');

RegExp 构造函数接收两个参数,第一个是正则的字符串表示,第二个是flag。由于接收的是字符串形式,所以正则表达式中出现的转义字符要进行双重转义。

var pattern1 = /^\[abc\]$/i;
pattern1.test('[ABC]'); // true

var pattern2 = new RegExp('^\\[abc\\]$', 'i');
pattern2.test('[ABC]'); //true

 

动态创建RegExp

有时候需要匹配的正则模式不是固定的,这种情况下就不好使用正则的字面量写法了。

var text = '1,2,3,4,5,6,7,8,9,0',
    randomNum = Math.floor(Math.random() * 10),
    result = text.replace(new RegExp('\\b'+randomNum+'\\b'), ' ');

以上代码会随机将一个数字替换为空,这里要注意前面说过的双重转义问题。

 

感谢你的浏览,希望能对你有所帮助。