正则又叫规则或模式,是一个强大的字符串匹配工具。javascript 通过 RegExp 类型来支持正则表达式,本文给大家介绍 javascript 类型系统之正则表达式,对 js 正则表达式相关知识感兴趣的朋友一起学习吧
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
定义
正则又叫规则或模式,是一个强大的字符串匹配工具。javascript 通过 RegExp 类型来支持正则表达式
特性
[1] 贪婪性,匹配最长的
[2] 懒惰性,不设置 / g,则只匹配第 1 个
写法
perl 写法 (使用字面量形式)
var expression = /pattern/flags;
模式 (pattern) 部分可以是任何简单或复杂的正则表达式,可以包含字符串、限定类、分组、向前查找以及反向引用。每个正则表达式可以带一个或多个标志(flags),用以标明正则表达式的行为。正则表达式支持三个标志:
[1]g: 表示全局模式 (global)
[2]i: 表示不区分大小写 (ignoreCase)
[3]m: 表示多行模式 (multiline)
- //匹配字符串所有'at'的实例
- var pattern1 = /at/g;
RegExp 构造函数
RegExp 构造函数接收两个参数: 要匹配的字符串模式 (pattern) 和标志字符串(flags)(可选)
[注意]RegExp 构造函数的两个参数都是字符串。且使用字面量形式定义的任何表达式都可使用构造函数
- //匹配字符串所有'at'的实例
- var pattern = new RegExp('at','g');
两种写法的区别
字面量写法不支持变量,只能用构造函数的形式来写
[tips] 获取 class 元素 (因为 classname 是变量, 只能使用构造函数的形式)
- function getByClass(obj,classname){
- var elements = obj.getElementsByTagName('*');
- var result = [];
- var pattern = new RegExp( '(^|\\s)'+ classname + '(\\s|$)');
- for(var i = 0; i < elements.length; i++){
- if(pattern.test(elements[i].className)){
- result.push(elements[i]);
- }
- }
- return result;
- }
[注意]ES3 中,正则表达式字面量始终共享同一个 RegExp 实例,而使用构造函数创建的每一个新 RegExp 实例都是一个新实例。ES5 中规定使用正则字面量必须像直接调用 RegExp 构造函数一样,每次都创建新的 RegExp 实例
语法
[注意] 正则表达式中不能出现多余空格
元字符 (14 个)
() [] {} \ ^ $ | ? * + .
[注意] 元字符必须转义,即用 \ 加转义字符,用 new RegExp 写的正则必须双重转义
转义字符
. 除换行符 \ n 之外的任意字符
\d 数字
\D 非数字
\w 字母、数字、下划线
\W 非字母、数字、下划线 (汉字不属于 \ w)
\s 空格
\S 非空格
\b 边界符 (\w 的左侧或右侧不是 \ w,则会出现一个边界符)
\B 非边界符
\1 表示和前面相同的一个字符
\t 制表符
\v 垂直制表符
\uxxxx 查找以十六进制 xxxx 规定的 Unicode 字符 (\u4e00-\u9fa5 代表中文)
(\w)(\d)\1\2 :\1 代表 \ w 当时所代表的值,\2 代表 \ d 当时所代表的值
[注意] 正则表达式中的子项必须是用小括号括起来的,并且顺序以小括号的前括号出现的顺序为准
[tips] 找出重复项最多的字符和个数
- var str = 'aaaaabbbbbdddddaaaaaaaffffffffffffffffffgggggcccccce';
- var pattern = /(\w)\1+/g;
- var maxLength = 0;
- var maxValue = '';
- var result = str.replace(pattern,
- function(match, match1, pos, originalText) {
- if (match.length > maxLength) {
- maxLength = match.length;
- maxValue = match1;
- }
- }) console.log(maxLength, maxValue); //18 "f"
系统转义
alert() 和 console.log() 里面的字符是系统转义字符
\0 空字节
\n 换行
\t 制表
\b 空格
\r 回车
\f 进纸
\\ 斜杠
\' 单引号
\" 双引号
\xnn 以十六进制 nn 表示一个字符 (n 为 0-f),如 \ x41 表示'A'
\unnnn 以十六进制 nnnn 表示一个 Unicode 字符 (n 为 0-f),如 \ u03a3 表示希腊字符ε
[注意]alert 里面的换行不能用
或
,而应该用 \ n
- alert('http://www.baidu.com\n\t你好')
双重转义
由于 RegExp 构造函数的参数是字符串,所以某些情况下,需要对字符进行双重转义。所有元字符必须双重转义,已经转义过的字符也必须双重转义
- 字面量模式 -> 等价的字符串
- /\[bc\]at/ "\\[bc\\]at"
- /\.at/ "\\.at"
- /name\/age/ "name\\/age"
- /\d.\d{1,2}/ "\\d.\\d{1,2}"
- /\w\\hello\\123/ "\\w\\\\hello\\\\123"
量词
{n} 匹配 n 次
{n,m} 匹配至少 n 次,最多 m 次
{n,} 匹配至少 n 次
? 相当于 {0,1}
* 相当于 {0,}
+ 相当于 {1,}
位置符号
^ 起始符号
$ 结束符号
?= 肯定正向环视
?! 否定正向环视
控制符号
[] 候选
| 或
^ 非
- 到
(red|blue|green) 查找任何指定的选项
[abc] 查找方括号之间的任何字符
[^abc] 查找任何不在方括号之间的字符
[0-9] 查找任何从 0 到 9 的数字
[a-z] 查找任何从小写 a 到小写 z 的字符
[A-Z] 查找任何从大写 A 到大写 Z 的字符
[A-z] 查找任何从大写 A 到小写 z 的字符
[adgk] 查找给定集合内的任何字符
[^adgk] 查找给定集合外的任何字符
$ 符号
$$ $
$& 匹配整个模式的子字符串 (与 RegExp.lastMatch 的值相同)
$` 匹配子字符串之前的子字符串 (与 RegExp.leftContext 的值相同)
$'匹配子字符串之后的子字符串 (与 RegExp.rightContext 的值相同)
$n 匹配第 n 个捕获组的子字符串,其中 n 等于 0-9。$1 表示匹配第一个捕获组的子字符串 (从第 1 个算起)
$nn 匹配第 nn 个捕获组的子字符串,其中 nn 等于 01-99
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$0')) //$0,$0,$0,$0
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$1')) //ca,ba,sa,fa
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$2')) //t,t,t,t
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$3')) //$3,$3,$3,$3
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$$')) //$,$,$,$
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$&')) //cat,bat,sat,fat
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, '$`')) //,cat,,cat,bat,,cat,bat,sat,
- console.log('cat,bat,sat,fat'.replace(/(.a)(t)/g, "$'")) //,bat,sat,fat,,sat,fat,,fat,
构造函数属性
适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。关于这些属性的独特之处在于可以通过两种方式访问它们,即长属性名和短属性名。短属性名大都不是有效的 ECMAScript 标识符,所以必须通过方括号语法来访问它们
长属性名 短属性名 说明
input $_ 最近一次要匹配的字符串
lastMatch $& 最近一次的匹配项
lastParen $+ 最近一次匹配的捕获组
leftContext $` input 字符串中 lastMatch 之前的文本
multiline $* 布尔值,表示是否所有表达式都使用多行模式
rightContext $' Input 字符串中 lastMarch 之后的文本
使用这些属性,可以从 exec() 方法或 text() 方法执行的操作中提取出更具体的信息
- var text = 'this has been a short summer';
- var pattern = /(.)hort/g;
- if(pattern.test(text)){
- console.log(RegExp.input);//'this has been a short summer'
- console.log(RegExp.leftContext);//'this has been a '
- console.log(RegExp.rightContext);//' summer'
- console.log(RegExp.lastMatch);//'short'
- console.log(RegExp.lastParen);//'s'
- console.log(RegExp.multiline);//false
- console.log(RegExp['$_']);//'this has been a short summer'
- console.log(RegExp['$`']);//'this has been a '
- console.log(RegExp["$'"]);//' summer'
- console.log(RegExp['$&']);//'short'
- console.log(RegExp['$+']);//'s'
- console.log(RegExp['$*']);//false
- }
//javascript 有 9 个用于存储捕获组的构造函数属性。RegExp.$1\RegExp.$2\RegExp.$3…… 到 RegExp.$9 分别用于存储第一、第二…… 第九个匹配的捕获组。在调用 exec() 或 test() 方法时,这些属性会被自动填充
- var text = 'this has been a short summer';
- var pattern = /(..)or(.)/g;
- if(pattern.test(text)){
- console.log(RegExp.$1);//sh
- console.log(RegExp.$2);//t
- }
实例属性
通过实例属性可以获知一个正则表达式的各方面信息,但却没多大用处,因为这些信息都包含在模式声明中
global: 布尔值,表示是否设置了 g 标志
ignoreCase: 布尔值,表示是否设置了 i 标志
lastIndex: 整数,表示开始搜索下一个匹配项的字符位置,从 0 算起
multiline: 布尔值,表示是否设置了标志 m
source: 正则表达式的字符串表示,按照字面量形式而非传入构造函数中的字符串模式返回
- var pattern = new RegExp('\\[bc\\]at', 'i');
- console.log(pattern.global); //false
- console.log(pattern.ignoreCase); //true
- console.log(pattern.multiline); //false
- console.log(pattern.lastIndex); //0
- console.log(pattern.source); //'\[bc\]at'
继承的方法
共 toString()、toLocaleString() 和 valueOf() 三个方法,且都返回正则表达式字面量,与创建正则表达式的方式无关。要注意的是 toString() 和 toLocaleString() 返回的正则表达式的字符串表示,而 valueOf 返回的是正则表达式对象本身
- var pattern = new RegExp('\\[bc\\]at', 'gi');
- console.log(pattern.toString()); // '/\[bc\]at/gi'
- console.log(pattern.toLocaleString()); // '/\[bc\]at/gi'
- console.log(pattern.valueOf()); // /\[bc\]at/gi
实例方法
exec()
专门为捕获组而设计,接受一个参数,即要应用模式的字符串。然后返回包含第一个匹配项信息的数组。在没有匹配项的情况下返回 null。返回的数组包含两个额外的属性:index 和 input。index 表示匹配项在字符串的位置,input 表示应用正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串,如果模式中没有捕获组,则该数组只包含一项
- var text = 'mom and dad and baby and others';
- var pattern = /mom( and dad( and baby)?)?/gi;
- var matches = pattern.exec(text);
- console.log(pattern, matches);
- //pattern.lastIndex:20
- //matches[0]:'mom and dad and baby'
- //matches[1]:' and dad and baby'
- //matches[2]:' and baby'
- //matches.index:0
- //matches.input:'mom and dad and baby and others'
[注意]对于 exec()方法而言,即使在模式中设置了全局标志 (g),它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用 exec(),将始终返回第一个匹配项的信息;而在设置全局标志的情况下,每次调用 exec() 都会在字符串中继续查找新匹配项。IE8 - 在 lastIndex 属性上存在偏差,即使在非全局模式下,lastIndex 属性每次也会变化
- var text = 'cat,bat,sat,fat';
- var pattern1 = /.at/;
- var matches = pattern1.exec(text);
- console.log(pattern1, matches);
- //pattern1.lastIndex:0
- //matches[0]:'cat'
- //matches.index:0
- //matches.input:'cat,bat,sat,fat'
- var text = 'cat,bat,sat,fat';
- matches = pattern1.exec(text);
- console.log(pattern1, matches);
- //pattern1.lastIndex:0
- //matches[0]:'cat'
- //matches.index:0
- //matches.input:'cat,bat,sat,fat'
- var text = 'cat,bat,sat,fat';
- var pattern2 = /.at/g;
- var matches = pattern2.exec(text);
- console.log(pattern2, matches);
- //pattern2.lastIndex:3
- //matches[0]:'cat'
- //matches.index:0
- //matches.input:'cat,bat,sat,fat'
- var text = 'cat,bat,sat,fat';
- matches = pattern2.exec(text);
- console.log(pattern2, matches);
- //pattern2.lastIndex:7
- //matches[0]:'bat'
- //matches.index:4
- //matches.input:'cat,bat,sat,fat'
[tips] 用 exec() 方法找出匹配的所有位置和所有值
- var string = 'j1h342jg24g234j 3g24j1';
- var pattern = /\d/g;
- var valueArray = [];//值
- var indexArray = [];//位置
- var temp = pattern.exec(string);
- while(temp != null){
- valueArray.push(temp[0]);
- indexArray.push(temp.index);
- temp = pattern.exec(string);
- }
- //["1", "3", "4", "2", "2", "4", "2", "3", "4", "3", "2", "4", "1"] [1, 3, 4, 5, 8, 9, 11, 12, 13, 16, 18, 19, 21]
- console.log(valueArray,indexArray);
test()
接受一个字符串参数,在模式与该参数匹配的情况下返回 true, 否则返回 false
[注意] 常用于只想知道目标字符串与某个模式是否匹配,但不需要知道其文本内容的情况, 经常用在 if 语句中
- var text = '000-00-000';
- var pattern = /\d{3}-\d{2}-\d{4}/;
- if(pattern.test(text)){
- console.log('The pattern was matched');
- }
模式匹配方法
String 类型定义了几个用于在字符串中匹配模式的方法
match()
只接受一个参数,正则或字符串,把匹配的内容保存到一个数组中返回
[注意] 加上全局标记时,match() 方法返回值中没有 index 和 input 属性
[1] 不加 / g
- var string = 'cat,bat,sat,fat';
- var pattern = /.at/;
- var matches = string.match(pattern);
- console.log(matches, matches.index, matches.input); //['cat'] 0 'cat,bat,sat,fat'
[2] 加 / g
- var string = 'cat,bat,sat,fat';
- var pattern = /.at/g;
- var matches = string.match(pattern);
- console.log(matches, matches.index, matches.input); //['cat','bat','sat','fat'] undefined undefined
[3] 字符串
- var string = 'cat,bat,sat,fat';
- var pattern = 'at';
- var matches = string.match(pattern);
- console.log(matches,matches.index,matches.input);//['at'] 1 'cat,bat,sat,fat'
- search()
只接受一个参数,正则或字符串,返回匹配的内容在字符串中首次出现的位置,类似于不能设置起始位置的 indexOf,找不到返回 - 1
[1] 正则 (加 / g 和不加 / g 效果一样)
- var string = 'cat,bat,sat,fat';
- var pattern = /.at/;
- var pos = string.search(pattern);
- console.log(pos); //0
[2] 字符串
- var string = 'cat,bat,sat,fat';
- var pattern = 'at';
- var pos = string.search(pattern);
- console.log(pos); //1
[tips] 找出匹配的所有位置
- function fnAllSearch(str, pattern) {
- var pos = str.search(pattern);
- var length = str.match(pattern)[0].length;
- var index = pos + length;
- var result = [];
- var last = index;
- result.push(pos);
- while (true) {
- str = str.substr(index);
- pos = str.search(pattern);
- if (pos === -1) {
- break;
- }
- length = str.match(pattern)[0].length;
- index = pos + length;
- result.push(last + pos);
- last += index;
- }
- return result;
- }
- console.log(fnAllSearch('cat23fbat246565sa3dftf44at', /\d+/)); //[3,9,17,22]
replace()
该方法接收两个参数: 第一个为正则表达式或字符串 (待查找的内容)、第二个为字符串或函数 (替换的内容)
[1] 字符串替换
- var string = 'cat,bat,sat,fat';
- var result = string.replace('at', 'ond');
- console.log(result); //'cond,bat,sat,fat'
[2] 正则无 / g 替换
- var string = 'cat,bat,sat,fat';
- var result = string.replace(/at/, 'ond');
- console.log(result); //'cond,bat,sat,fat'
[3] 正则有 / g 替换
- var string = 'cat,bat,sat,fat';
- var result = string.replace(/at/g, 'ond');
- console.log(result); //'cond,bond,sond,fond'
[4] 函数替换
在只有一个匹配项 (即与模式匹配的字符串的情况下,会向这个函数传递 3 个参数: 模式的匹配项、模式匹配项在字符串中的位置、原始字符串。在正则表达式定义了多个捕获组的情况下,传递给函数的参数依次是模式的匹配项、第一个捕获组的匹配项、第二个捕获组的匹配项…… 第 N 个捕获组的匹配项,但最后两个参数仍然分别是模式的匹配项在字符串中的位置和原始字符串,这个函数返回一个字符串
- var string = 'cat,bat,sat,fat';
- var index = 0;
- var result = string.replace(/at/g,
- function(match, pos, originalText) {
- index++;
- if (index == 2) {
- return 'wow';
- } else {
- return '0';
- }
- });
- console.log(result); //'c0,bwow,s0,f0'
[tips] 防止跨站脚本攻击 xss(css)
- function htmlEscape(text) {
- return text.replace(/[<>"&]/g,
- function(match, pos, originalText) {
- switch (match) {
- case '<':
- return '<';
- case '>':
- return '>';
- case '&':
- return '&';
- case '\"':
- return '"';
- }
- });
- }
- console.log(htmlEscape('<p class=\"greeting\">Hello world!</p>'));
- //<p class=" greeting">Hello world!</p>
- console.log(htmlEscape('<p class="greeting">Hello world!</p>'));
- //同上
split()
这个方法可以基于指定的分隔符将一个字符串分割成多个字符串,并将结果放在一个数组中,分隔符可以是字符串,也可以是一个 RegExp。该方法可以接受第二个参数 (可选) 用于指定数组的大小,如果第二个参数为 0-array.length 范围内的值时按照指定参数输出,其他情况将所有结果都输出
[注意]IE8 - 对 split() 中的正则表达式,会忽略捕获组
[tips] 如果是 split(''),则原来的数组会一个字符字符分割后传出来
- var colorText = 'red,blue,green,yellow';
- console.log(colorText.split('')); //["r", "e", "d", ",", "b", "l", "u", "e", ",", "g", "r", "e", "e", "n", ",", "y", "e", "l", "l", "o", "w"]
- console.log(colorText.split(',')); //["red", "blue", "green", "yellow"]
- console.log(colorText.split(',', 2)); //["red", "blue"]
- console.log(colorText.split(/\,/)); //["red", "blue", "green", "yellow"]
- console.log(colorText.split(/e/)); //["r", "d,blu", ",gr", "", "n,y", "llow"]
- console.log(colorText.split(/[^\,]+/)); //将除去逗号以外的字符串变为分隔符["", ",", ",", ",", ""],IE8-会识别为[",",",",","]
局限性
下列为 ECMAScript 正则表达式不支持的特性
[1] 匹配字符串开始的结尾的 \ A 和 \ Z 锚 (但支持以 ^ 和 $ 来匹配字符串的开始和结尾)
[2] 向后查找 (但支持向前查找)
[3] 并集和交集类
[4] 原子组
[5]Unicode 支持 (单个字符除外)
[6] 命名的捕获组 (但支持编号的捕获组)
[7]s(single 单行) 和 x(free-spacing 无间隔) 匹配模式
[8] 条件匹配
[9] 正则表达式注释
常见实例
[1] 两种方法找出字符串中所有的数字
[a] 用传统字符串操作
- var str1 = 'j1h342jg24g234j 3g24j1';
- var array = [];
- var temp = '';
- for (var i = 0; i < str1.length; i++) {
- var value = parseInt(str1.charAt(i)); //如果用Number()将无法排除空格
- if (!isNaN(value)) {
- temp += str1.charAt(i);
- } else {
- if (temp != '') {
- array.push(temp);
- temp = '';
- }
- }
- }
- if (temp != '') {
- array.push(temp);
- temp = '';
- }
- console.log(array); //["1", "342", "24", "234", "3", "24", "1"]
[b] 用正则表达式
- var str1 = 'j1h342jg24g234j 3g24j1';
- array = str1.match(/\d+/g);
- console.log(array); //["1", "342", "24", "234", "3", "24", "1"]
[2] 敏感词过滤 (replace 方法的函数匹配)
- var string = 'FLG是邪教';
- var pattern = /FLG|邪教/g;
- var result = string.replace(pattern,
- function($0) {
- var s = '';
- for (var i = 0; i < $0.length; i++) {
- s += '*';
- }
- return s;
- }) console.log(result); //***是**
[3] 日期格式化
- var array = ['2015.7.28', '2015-7-28', '2015/7/28', '2015.7-28', '2015-7.28', '2015/7---28'];
- function formatDate(date) {
- return date.replace(/(\d+)\D+(\d+)\D+(\d+)/, '$1' + '年' + '$2' + '月' + '$3' + '日')
- }
- var result = [];
- for (var i = 0; i < array.length; i++) {
- result.push(formatDate(array[i]));
- }
- console.log(result); //["2015年7月28日", "2015年7月28日", "2015年7月28日", "2015年7月28日", "2015年7月28日", "2015年7月28日"]
[4] 获取网页中的文本内容
- var str = '<p>refds</p><p>fasdf</p>'
- var pattern = /<[^<>]+>/g;
- console.log(str.replace(pattern, '')); //refdsfasdf
[5] 去除首尾空格的 trim() 兼容写法
- var string = ' my name is littlematch ';
- console.log(string.replace(/^\s+|\s+$/, '')); //my name is littlematch
关于 JavaScript 类型系统之正则表达式 的全部内容就给大家介绍到这里,希望本文所述能够帮助到大家。
来源: http://www.phperz.com/article/17/0216/267738.html