正则表达式
JavaScript 字符串是在编程中使用最多的一种数据类型,很多地方都需要对字符串进行操作,例如判断一个字符串是否为一个合法的 E-mail 地址、从字符串截取指定的部分等。
正则表达式是一种用于匹配字符串或特殊字符的一种逻辑公式,所谓逻辑公式就是由一些特定字符组合成的,用来表示某些规则的特殊字符串,可以表达对字符串数据的过滤逻辑。
什么是正则表达式
正则表达式(regular expression)是一种表达文本模式(即字符串结构)的方法,有点像字符串的模板,常常用来按照“给定模式”匹配文本。比如,正则表达式给出一个 Email 地址的模式,然后用它来确定一个字符串是否为 Email 地址。JavaScript 的正则表达式体系是参照 Perl 5 建立的。
| 符号 | 释义 |
|---|---|
| ^ | 表示匹配开头 |
| $ | 表示匹配结尾 |
| \d | 表示匹配数字 |
示例1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '223344'; // 需要验证的字符串
var regexp = /^\d{6}$/; // 正则表达式规则
if (regexp.test(str)) {
alert('验证成功');
} else {
alert('验证失败');
}
</script>
</body>
</html>
示例2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 以m开头 n结尾 中间是6位数字
var regexp = /^m\d{6}n$/;
var str1 = 'm563421n';
var str2 = 'm56342n';
var str3 = 'm5634 1n';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
console.log(regexp.test(str3));
</script>
</body>
</html>
正则表达式的创建
新建正则表达式有两种方法。一种是使用字面量,以斜杠表示开始和结束。
var regex = /xyz/;
另一种是使用RegExp构造函数。
var regex = new RegExp('xyz');
上面两种写法是等价的,都新建了一个内容为xyz的正则表达式对象。它们的主要区别是,第一种方法在引擎编译代码时,就会新建正则表达式,第二种方法在运行时新建正则表达式,所以前者的效率较高。而且,前者比较便利和直观,所以实际应用中,基本上都采用字面量定义正则表达式。
RegExp构造函数还可以接受第二个参数,表示修饰符(详细解释见下文)。
var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;
上面代码中,正则表达式/xyz/有一个修饰符i。
使用构造函数的形式去创建正则应注意如下:
正则表达式是引用类型值
正则表达式是引用类型值,所以两个正则表达式,是不可能相等的
它们比较的是内存中的地址是否相同
console.log(typeof regexp); // object
元字符
大部分字符在正则表达式中,就是字面的含义,比如
/a/匹配a,/b/匹配b。如果在正则表达式之中,某个字符只表示它字面的含义(就像前面的a和b),那么它们就叫做“字面量字符”(literal characters)。
/dog/.test('old dog') // true
上面代码中正则表达式的dog,就是字面量字符,所以/dog/匹配old dog,因为它就表示d、o、g三个字母连在一起。
除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做“元字符”(metacharacters),主要有以下几个。
(1)点字符(.)
点字符(.)匹配除回车(\r)、换行(\n) 、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符。注意,对于码点大于0xFFFF字符,点字符不能正确匹配,会认为这是两个字符。
/c.t/
上面代码中,c.t匹配c和t之间包含任意一个字符的情况,只要这三个字符在同一行,比如cat、c2t、c-t等等,但是不匹配coot。
(2)位置字符
位置字符用来提示字符所处的位置,主要有两个字符。
^表示字符串的开始位置$表示字符串的结束位置
// test必须出现在开始位置
/^test/.test('test123') // true
// test必须出现在结束位置
/test$/.test('new test') // true
// 从开始位置到结束位置只有test
/^test$/.test('test') // true
/^test$/.test('test test') // false
(3)选择符(|)
竖线符号(|)在正则表达式中表示“或关系”(OR),即cat|dog表示匹配cat或dog。
/11|22/.test('911') // true
上面代码中,正则表达式指定必须匹配11或22。
多个选择符可以联合使用。
// 匹配fred、barney、betty之中的一个
/fred|barney|betty/
选择符会包括它前后的多个字符,比如/ab|cd/指的是匹配ab或者cd,而不是指匹配b或者c。如果想修改这个行为,可以使用圆括号。
/a( |\t)b/.test('a\tb') // true
上面代码指的是,a和b之间有一个空格或者一个制表符。
选择符( | )解析:
要匹配的字符串是纯数字或纯字母,要如何书写正则表达式呢?
有的小伙伴已经想到了,写两个正则表达不就好了,如下面这种写法:
var str1 = "1111"
var str2 = "imooc"
var str3 = "1111imooc"
var reg1 = /^\d+$/ // 匹配纯数字
var reg2 = /^[a-zA-Z]+$/ //匹配纯字母
console.log(reg1.test(str1) || reg2.test(str1)) //true
console.log(reg1.test(str2) || reg2.test(str2)) //true
console.log(reg1.test(str3) || reg2.test(str3)) //false
上面代码中,str1是纯数字,符合第一个正则,匹配结果返回true, str2是纯字母,符合第二个正则,匹配结果返回true,st3是数字字母组成的,不符合条件,返回false。
这确实也是一种解决方式,但是四配的时候需要验证两次,才能知道这个字符串是纯数字还是纯字母,有些麻烦,接下来,讲解一种更简单直接的方式,元字符或
定义
正则中使用竖线 | 表示或,表示只匹配指定几项之间的一项
使用方式
对x|y表示匹配x或y,也就是说两种中匹配一个,只要匹配到其中一个,就不会再匹配另外一个了
示例1:
var str = "ab"
var reg = /a|ab/
console.log(reg.exec(str)) // a
上面这段代码中,/a|ab/表示匹配a或ab,从字符串左侧开始匹配,匹配到a时,就不会在匹配ab了,所以返回结果是a。
示例2:
var str1 = "imoochtmlcccjs"
var str2 = "jsimooccss"
var str3 = "cssimoochtml"
var reg = /html|css|js/
console.log(reg.exec(str1)) // html
console.log(reg.exec(str2)) // js
console.log(reg.exec(str3)) // css
上面这段这段代码中,str1中匹配到html就不会再匹配后面的js 了,所以返回结果是html,同理,匹配str2返回的结果是js,匹配str3返回的结果是css
经过上面的讲解,相信已经了解了元字符或的使用方式,那么我们就可以使用元字符或的方式,解决文章开头提到匹配纯数字或纯字母的问题了,代码如下:
var str1 = "1111"
var str2 = "imooc"
var str3 = "1111imooc"
var reg = /^\d+$|^[a-zA-Z]+$/
console.log(reg.test(str1)) // true
console.log(reg.test(str2)) // true
console.log(reg.test(str3)) // false
上面这段代码中,str1属于纯数字,匹配结果返回true,str2属于纯字母,匹配结果返回true,str3是由数字字母组成的,不符合纯数字或纯字母这个条件,匹配结果返回false
预定义模式
预定义模式指的是某些常见模式的简写方式。
\d匹配0-9之间的任一数字,相当于[0-9]。\D匹配所有0-9以外的字符,相当于[^0-9]。\w匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。\W除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。\s匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]。\S匹配非空格的字符,相当于[^ \t\r\n\v\f]。
// \s 的例子
/\s\w*/.exec('hello world') // [" world"]
元字符注意事项
元字符使用案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^\d{3}-\d{4}-\d{3}$/;
var str1 = '123-3456-990';
console.log(regexp.test(str1));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^\w{3}-\w{4}-\w{3}$/;
var str1 = 'abc-aiwe-ert';
var str2 = 'abc-aiwe-_rt';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
字符的转义
本章节中讲过^或#或.它们都有正则中代表的意义,如果说当需要被验证的字符串中本身就带有^或#或.的符号。
那么就可以直接加上一个反斜杠\让^或#或.这些符号代表它们自己本身。而不代表正则表达式中的意义。
正则表达式中那些有特殊含义的元字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠。比如要匹配+,就要写成+。
/1+1/.test('1+1')
// false
/1+1/.test('1+1')
// true
上面代码中,第一个正则表达式之所以不匹配,因为加号是元字符,不代表自身。第二个正则表达式使用反斜杠对加号转义,就能匹配成功。
正则表达式中,需要反斜杠转义的,一共有12个字符:^、.、[、$、(、)、|、*、+、?、{和``。需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。
(new RegExp('1+1')).test('1+1')
// false
(new RegExp('1\+1')).test('1+1')
// true
上面代码中,RegExp作为构造函数,参数是一个字符串。但是,在字符串内部,反斜杠也是转义字符,所以它会先被反斜杠转义一次,然后再被正则表达式转义一次,因此需要两个反斜杠转义。
正常来说#是不需要加反斜杠 \ 的,有经验的人,在任何符号前都可以加反斜杠,确保表达的是本身的意思
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^\d{3}\.\d{2}\^\d{2}\#\d{2}$/; // 正常来说#是不需要加反斜杠(\)的,有经验的人,在任何符号前都可以加反斜杠,确保表达的是本身的意思
var str = '123.45^67#89';
console.log(regexp.test(str));
</script>
</body>
</html>
练习题
单选1
单选2
多选
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '你好 欢迎来学习';
var pat = /\s/; // 不用开头和结尾
console.log(pat.test(str)); // true
</script>
</body>
</html>
单选
注意:
匹配除字母、数字或者下划线以外的字符。等价于[ ^A-Za-z0-9_ ]
^叫元字符,元字符放在不同的位置是有不同的含义,比如说元字符放到“/^****/中”,例如:/^A-Za-z0-9_/ ,等价于开头第一个字符可以是大写字母A到Z,也可以是小写字母a到z,也可以是数字0到9,也可以是下划线。
那么如果^元字符放入到“[^****]”,例如[^A-Za-z0-9_] ,则是代表不可以是大写字母A到Z,也不可以是小写字母a到z,也不可以是数字0到9也,也不可以是下划线。
方括号表示法
方括号的使用
字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内,比如
[xyz] 表示x、y、z之中任选一个匹配。
/[abc]/.test('hello world') // false
/[abc]/.test('apple') // true
上面代码中,字符串hello world不包含a、b、c这三个字母中的任一个,所以返回false;字符串apple包含字母a,所以返回true。
有两个字符在字符类中有特殊含义。
(1)脱字符(^)
如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。比如,[^xyz]表示除了x、y、z之外都可以匹配。
/[^abc]/.test('bbc news') // true
/[^abc]/.test('bbc') // false
上面代码中,字符串bbc news包含a、b、c以外的其他字符,所以返回true;字符串bbc不包含a、b、c以外的其他字符,所以返回false。
如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符。相比之下,点号作为元字符(.)是不包括换行符的。
var s = 'Please yes\nmake my day!';
s.match(/yes.*day/) // null
s.match(/yes[^]*day/) // [ 'yes\nmake my day']
上面代码中,字符串s含有一个换行符,点号不包括换行符,所以第一个正则表达式匹配失败;第二个正则表达式[^]包含一切字符,所以匹配成功。
注意,脱字符只有在字符类的第一个位置才有特殊含义,否则就是字面含义。
(2)连字符(-)
某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。比如,[abc]可以写成[a-c],[0123456789]可以写成[0-9],同理[A-Z]表示26个大写字母。
/a-z/.test('b') // false
/[a-z]/.test('b') // true
上面代码中,当连字号(dash)不出现在方括号之中,就不具备简写的作用,只代表字面的含义,所以不匹配字符b。只有当连字号用在方括号之中,才表示连续的字符序列。
以下都是合法的字符类简写形式。
[0-9.,]
[0-9a-fA-F]
[a-zA-Z0-9-]
[1-31]
上面代码中最后一个字符类[1-31],不代表1到31,只代表1到3。
连字符还可以用来指定 Unicode 字符的范围。
var str = "\u0130\u0131\u0132";
/[\u0128-\uFFFF]/.test(str)
// true
上面代码中,\u0128-\uFFFF表示匹配码点在0128到FFFF之间的所有字符。
另外,不要过分使用连字符,设定一个很大的范围,否则很可能选中意料之外的字符。最典型的例子就是[A-z],表面上它是选中从大写的A到小写的z之间52个字母,但是由于在 ASCII 编码之中,大写字母与小写字母之间还有其他字符,结果就会出现意料之外的结果。
/[A-z]/.test('\') // true
上面代码中,由于反斜杠('')的ASCII码在大写字母与小写字母之间,结果会被选中。
练习示例
题目1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^[a-zA-z]{5}$/;
var str1 = 'aserg';
var str2 = 'asergq';
var str3 = 'a_ergq';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
console.log(regexp.test(str3));
</script>
</body>
</html>
题目2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^[a-z\.]{5}$/;
var str1 = 'as..g';
var str2 = 'ase/d';
var str3 = 'ase u';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
console.log(regexp.test(str3));
</script>
</body>
</html>
题目3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^[a-z]{3}[a-ln-z]$/;
var str1 = 'qwen';
var str2 = 'asdm';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
编程练习1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^1[3-9]\d{5}$/;
var str1 = '1343219';
var str2 = '1243219';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
编程练习2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^\w{5}[^0]$/;
var str1 = 'as34__';
var str2 = 'as34_0';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
量词
重复类
模式的精确匹配次数,使用大括号({})表示。{n}表示恰好重复n次,{n,}表示至少重复n次,{n,m}表示重复不少于n次,不多于m次。
/lo{2}k/.test('look') // true
/lo{2,5}k/.test('looook') // true
上面代码中,第一个模式指定o连续出现2次,第二个模式指定o连续出现2次到5次之间。
量词符
量词符用来设定某个模式出现的次数。
?问号表示某个模式出现0次或1次,等同于{0, 1}。*星号表示某个模式出现0次或多次,等同于{0,}。+加号表示某个模式出现1次或多次,等同于{1,}。
// t 出现0次或1次
/t?est/.test('test') // true
/t?est/.test('est') // true
// t 出现1次或多次
/t+est/.test('test') // true
/t+est/.test('ttest') // true
/t+est/.test('est') // false
// t 出现0次或多次
/t*est/.test('test') // true
/t*est/.test('ttest') // true
/t*est/.test('tttest') // true
/t*est/.test('est') // true
使用示例
题目1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^1\d{10}$/;
var str1 = '13355557777';
var str2 = '23355557777';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
题目2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^[a-zA-Z]\d+[a-zA-Z]$/;
var str1 = 'a1d';
var str2 = 'aed';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
题目3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var regexp = /^w{3}\.\w{1,}(\.com)|(\.com\.cn)$/;
var str1 = 'www.adf.com.cn';
var str2 = 'www.adf.com';
console.log(regexp.test(str1));
console.log(regexp.test(str2));
</script>
</body>
</html>
修饰符(flags)
修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。
修饰符可以单个使用,也可以多个一起使用。
// 单个修饰符
var regex = /test/i;
// 多个修饰符
var regex = /test/ig;
(1)g 修饰符
默认情况下,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。
var regex = /b/;
var str = 'abba';
regex.test(str); // true
regex.test(str); // true
regex.test(str); // true
上面代码中,正则模式不含g修饰符,每次都是从字符串头部开始匹配。所以,连续做了三次匹配,都返回true。
var regex = /b/g;
var str = 'abba';
regex.test(str); // true
regex.test(str); // true
regex.test(str); // false
上面代码中,正则模式含有g修饰符,每次都是从上一次匹配成功处,开始向后匹配。因为字符串abba只有两个b,所以前两次匹配结果为true,第三次匹配结果为false。
(2)i 修饰符
默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写(ignoreCase)。
/abc/.test('ABC') // false
/abc/i.test('ABC') // true
上面代码表示,加了i修饰符以后,不考虑大小写,所以模式abc匹配字符串ABC。
(3)m 修饰符
m修饰符表示多行模式(multiline),会修改^和$的行为。默认情况下(即不加m修饰符时),^和$匹配字符串的开始处和结尾处,加上m修饰符以后,^和$还会匹配行首和行尾,即^和$会识别换行符(\n)。
/world$/.test('hello world\n') // false
/world$/m.test('hello world\n') // true
上面的代码中,字符串结尾处有一个换行符。如果不加m修饰符,匹配不成功,因为字符串的结尾不是world;加上以后,$可以匹配行尾。
/^b/m.test('a\nb') // true
上面代码要求匹配行首的b,如果不加m修饰符,就相当于b只能处在字符串的开始处。加上m修饰符以后,换行符\n也会被认为是一行的开始。
正则表达式的相关方法
test()方法
RegExp.prototype.test()
正则实例对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串。
/cat/.test('cats and dogs') // true
上面代码验证参数字符串之中是否包含cat,结果返回true。
如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。
exec()方法
exec() 方法在一个指定字符串中执行一个搜索匹配。返回一个结果数组或 null
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123fds456jkt789';
var regexp = /\d+/; // 注意这里不需要指定开头和结尾
console.log(regexp.exec(str));
</script>
</body>
</html>
exec()方法逐条遍历
我们在使用exec()的时候往往都会加g修饰符的,如果不加,它只能找到最开头的一个
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123abc456def789';
var regexp = /\d+/g; // +表示贪婪的,尽可能多的匹配
var result = 0;
while (result = regexp.exec(str)) {
console.log(result);
}
</script>
</body>
</html>
注意 返回的是数组
解析
while(当检测结果存在的时候,它就会一直检测下去)
循环里面是一条赋值语句,赋值语句也是有返回值的,它的返回值就是等号右边的值
它一边在把等式右边的值赋给左边,一边在检测右面的值是否为真(true),不能为null。数组就是真,null为假;
我们也可以在这里输出索引为0的第一项,方便对查找的结果进行操作:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123abc456def789';
var regexp = /\d+/g;
var result = 0;
while (result = regexp.exec(str)) {
console.log(result[0]); // 我们也可以在这里输出索引为0的第一项,方便对查找的结果进行操作
}
</script>
</body>
</html>
练习题
练习1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = 'regular expression = regexp';
var regexp1 = /lar\sexp/;
var regexp2 = new RegExp('lar\\sexp');
document.write(regexp1.test(str) + '/');
document.write(regexp2.test(str) + '/');
document.write(regexp1.exec(str) + '/');
document.write(regexp2.exec(str) + '/');
</script>
</body>
</html>
练习2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '一个"普通字符"在匹配字符串的时候,匹配与它相同的一个字符';
var regexp1 = /\"普通字符\"/;
var regexp2 = new RegExp('\"普通字符\"');
document.write(regexp1.test(str) + '/');
document.write(regexp2.test(str) + '/');
document.write(regexp1.exec(str) + '/');
document.write(regexp2.exec(str) + '/');
</script>
</body>
</html>
练习3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = 'JavaScript_RegExp_5@gmail.com';
var regexp1 = /\_RegExp\_5\@gm/;
var regexp2 = new RegExp('\\_RegExp\\_5\\@gm');
var regexp3 = /\_RegExp\_5\@gm/i;
var regexp4 = new RegExp('\\_RegExp\\_5\\@gm', 'i');
document.write(regexp1.test(str) + '/');
document.write(regexp2.test(str) + '/');
document.write(regexp3.test(str) + '/');
document.write(regexp4.test(str) + '/');
document.write(regexp1.exec(str) + '/');
document.write(regexp2.exec(str) + '/');
document.write(regexp3.exec(str) + '/');
document.write(regexp4.exec(str) + '/');
</script>
</body>
</html>
字符串的相关正则方法
search()方法
String.prototype.search()
字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。如果没有任何匹配,则返回-1。
'_x_x'.search(/x/)
// 1
上面代码中,第一个匹配结果出现在字符串的1号位置。
全局匹配在search中没用。
search方法找到匹配的内容后,返回的是被匹配的字符第一位的下标值,没找到返回-1。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123saf567jig';
var regexp1 = /\d/g; // 全局匹配在search中没用
var regexp2 = /e/;
console.log(str.search(regexp1));
console.log(str.search(regexp2));
</script>
</body>
</html>
注意
-
search()方法可以通过正则来进行查找,而indexOf()不行
-
是字符串调用的search方法
match()方法
使用频率较高
String.prototype.match()
字符串实例对象的match方法对字符串进行正则匹配,返回匹配结果。
var s = '_x_x';
var r1 = /x/;
var r2 = /y/;
s.match(r1) // ["x"]
s.match(r2) // null
从上面代码可以看到,字符串的match方法与正则对象的exec方法非常类似:匹配成功返回一个数组,匹配失败返回null。
如果正则表达式带有g修饰符,则该方法与正则对象的exec方法行为不同,会一次性返回所有匹配成功的结果。
var s = 'abba';
var r = /a/g;
s.match(r) // ["a", "a"]
r.exec(s) // ["a"]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123asd789jid000';
var regexp1 = /\d+/g; // 注意这里都是全局搜素
var regexp2 = /\d/g;
console.log(str.match(regexp1));
console.log(str.match(regexp2));
</script>
</body>
</html>
replace()方法
String.prototype.replace()
字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。
str.replace(search, replacement)
正则表达式如果不加g修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。
'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"
'aaa'.replace(/a/g, 'b') // "bbb"
上面代码中,最后一个正则表达式使用了g修饰符,导致所有的a都被替换掉了。
replace方法的一个应用,就是消除字符串首尾两端的空格。
var str = ' #id div.class ';
str.replace(/^\s+|\s+$/g, '')
// "#id div.class"
再看如下demo
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123jsli456uibu345';
console.log(str.replace(/[a-z]/g, '*')); // 将字符串中的小写字母都替换为星号
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123jsli456uibu345';
console.log(str.replace(/[a-z]+/g, '*')); // 将字符串中的小写字母都替换为星号, +号表示尽可能多的匹配
</script>
</body>
</html>
split()方法
String.prototype.split()
字符串对象的split方法按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组。
str.split(separator, [limit])
该方法接受两个参数,第一个参数是正则表达式,表示分隔规则,第二个参数是返回数组的最大成员数。
// 非正则分隔
'a, b,c, d'.split(',')
// [ 'a', ' b', 'c', ' d' ]
// 正则分隔,去除多余的空格
'a, b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]
// 指定返回数组的最大成员
'a, b,c, d'.split(/, */, 2)
[ 'a', 'b' ]
上面代码使用正则表达式,去除了子字符串的逗号后面的空格。
// 例一
'aaa*a*'.split(/a*/)
// [ '', '*', '*' ]
// 例二
'aaa**a*'.split(/a*/)
// ["", "*", "*", "*"]
上面代码的分割规则是0次或多次的a,由于正则默认是贪婪匹配,所以例一的第一个分隔符是aaa,第二个分割符是a,将字符串分成三个部分,包含开始处的空字符串。例二的第一个分隔符是aaa,第二个分隔符是0个a(即空字符),第三个分隔符是a,所以将字符串分成四个部分。
如果正则表达式带有括号,则括号匹配的部分也会作为数组成员返回。
'aaa*a*'.split(/(a*)/)
// [ '', 'aaa', '*', 'a', '*' ]
上面代码的正则表达式使用了括号,第一个组匹配是aaa,第二个组匹配是a,它们都作为数组成员返回。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '123lsdf999ueroit789';
console.log(str.split(/\d+/g));
</script>
</body>
</html>
练习题
单选1
单选2
练习1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = '110报警120急救119火警114查询';
document.write(str.match(/\d+/g));
</script>
</body>
</html>
练习2
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var str = "2020.02.02";
console.log(str.replace(/\.+/g, '-'));
</script>
</body>
</html>
正则表达式的应用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
p>span {
color: red;
font-size: 14px;
display: none;
}
</style>
</head>
<body>
<p>
姓名:
<input class="nameFiled" type="text">
<span id="nameWarning">姓名不合法</span>
</p>
<p>
电话:
<input class="telField" type="text">
<span id="telWarning">电话不合法</span>
</p>
<p>
Email:
<input class="eField" type="email">
<span id="eWarning">Email不合法</span>
</p>
<script>
// 正则验证
var NameReg = /^[\u4e00-\u9fa5]{2,4}$/;
var TelReg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/;
var EmailReg = /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
// 输入框节点
var nameFiled = document.getElementsByClassName('nameFiled')[0];
var telField = document.getElementsByClassName('telField')[0];
var eField = document.getElementsByClassName('eField')[0];
// 警示文字节点
var nameWarning = document.getElementById('nameWarning');
var telWarning = document.getElementById('telWarning');
var eWarning = document.getElementById('eWarning');
// 事件触发
nameFiled.addEventListener('blur', function () {
if (NameReg.test(nameFiled.value)) {
nameWarning.style.display = 'none';
} else {
nameWarning.style.display = 'inline';
}
}, false);
telField.addEventListener('blur', function () {
if (TelReg.test(telField.value)) {
telWarning.style.display = 'none';
} else {
telWarning.style.display = 'inline';
}
}, false);
eField.addEventListener('blur', function () {
if (EmailReg.test(eField.value)) {
eWarning.style.display = 'none';
} else {
eWarning.style.display = 'inline';
}
}, false);
</script>
</body>
</html>
注册功能
任务描述
1、用户名输入框,正确的条件是:6-30位字母、数字或_, 以字母开头。
(1) 如果输入内容的不满足条件时,输入框后面的提示内容为。6-30位字母、数字或’_’,字母开头,且字体颜色变为红色。
(2) 如果输入的满足条件,输入框后面的提示内容为:“用户名输入正确”,且字体颜色变成绿色。
2、密码输入框,正确的条件是:6-20位字母或数字组成
(1) 如果输入内容的不满足条件时,输入框下面给出提示内容为:6-20位字母或数字,且字体颜色变为红色。
(2) 如果输入的密码内容是纯数字、纯小写字母或者纯大写字母,密码强度为低,只有第一块变为红色。
(3) 如果是两种类型的结合,那么密码强度为一般,第二块变为橘色。
(4) 如果是三种类型的结合,那么密码强度为高,第三块变为绿色。
3、密码确认框,正确的条件是:与上面的密码输入框的内容一致。
(1) 如果为空,那么后面给出文字提示“输入框不能为空”,且字体颜色变为红色。
(2) 如果输入的密码跟上面的密码不一致,则提示“两次密码输入不一致,请重新输入”且字体颜色变为红色。
(3) 如果输入的密码跟上面一致,则提示“两次输入一致”。
4、满足所有的验证条件,点击下一步提示“信息填写正确”,否则提示“请填写正确的信息”
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
p span.star {
color: orange;
}
input.submit {
width: 120px;
height: 40px;
margin-left: 50px;
background-color: #FFA500;
border-radius: 5px;
color: aliceblue;
}
input.submit:hover {
background-color: #FA7402;
}
p .user_warning,
p .password_warning_one,
p .password_warning_two,
p .password_warning_three {
color: red;
display: none;
}
p span.user_correct {
color: #1BBB76;
display: none;
}
p span.password_correct {
color: #1BBB76;
display: none;
}
p span.tip_wrap {
line-height: 23px;
display: none;
}
p span.tip_wrap .tips {
width: 30px;
height: 8px;
display: inline-block;
}
span.tip_wrap .tip_one {
background-color: red;
}
span.tip_wrap .tip_two {
background-color: orange;
}
span.tip_wrap .tip_three {
background-color: green;
}
</style>
</head>
<body>
<p>
<span class="star">*</span><span>用 户 名 :</span>
<input class="input_field" type="text" placeholder="用户设置成功后不可修改">
<span class="user_warning">6-30位字母、数字或“_”,字母开头</span>
<span class="user_correct">用户名输入正确</span>
</p>
<p>
<span class="star">*</span><span>登录密码:</span>
<input class="password_field_one" type="password" placeholder="6-20位字母或数字">
<span class="password_warning_one">6-20位字母或数字</span>
<span class="tip_wrap">
<span class="tips tip_one"></span>
<span class="tips tip_two"></span>
<span class="tips tip_three"></span>
</span>
</p>
<p>
<span class="star">*</span><span>确认密码:</span>
<input class="password_field_two" type="password" placeholder="请再次输入您的登录密码">
<span class="password_warning_two">输入框不能为空</span>
<span class="password_warning_three">两次密码输入不一致,请重新输入</span>
<span class="password_correct">信息填写正确</span>
</p>
<input class="submit" type="submit"></input>
<script>
// 节点获取
var inputField = document.getElementsByClassName('input_field')[0];
var passwordFieldOne = document.getElementsByClassName('password_field_one')[0];
var passwordFieldTwo = document.getElementsByClassName('password_field_two')[0];
var userCorrect = document.querySelector('p span.user_correct');
var userWarning = document.querySelector('p .user_warning');
var passwordWarningOne = document.querySelector('p .password_warning_one');
var passwordWarningTwo = document.querySelector('p .password_warning_two');
var passwordWarningThree = document.querySelector('p .password_warning_three');
var passwordCorrect = document.querySelector('p span.password_correct');
var tipWrap = document.querySelector('p span.tip_wrap');
var tipOne = document.querySelector('span.tip_wrap .tip_one');
var tipTwo = document.querySelector('span.tip_wrap .tip_two');
var tipThree = document.querySelector('span.tip_wrap .tip_three');
var submitBtn = document.querySelector('input.submit');
// 正则验证
var inputRegexp = /^[a-zA-Z]\w{5,29}$/; // 用户名验证
var passwordCorrectRegexp = /[a-zA-Z\d]{6,20}/;
var passwordGradeOne = /(^\d+$)|(^[a-z]+$)|(^[A-Z]+$)/;
var passwordGradeTwo = /(^[a-zA-Z]+$)|(^[a-z\d]+$)|(^[A-Z\d]+$)/;
var passwordGradeThree = /^[a-zA-Z\d]+$/;
// 提交按钮最终判断
var userBool = false;
var pwdBoolOne = false;
var pwdBoolTwo = false;
// 用户名输入判断
inputField.addEventListener('blur', function () {
if (inputRegexp.test(inputField.value)) {
userCorrect.style.display = 'inline';
userWarning.style.display = 'none';
userBool = true;
} else {
userWarning.style.display = 'inline';
userCorrect.style.display = 'none';
}
}, false);
// 第一次密码输入判断
passwordFieldOne.addEventListener('input', function () {
if (passwordCorrectRegexp.test(passwordFieldOne.value)) {
passwordWarningOne.style.display = 'none';
tipWrap.style.display = 'inline-block';
pwdBoolOne = true;
if (passwordGradeOne.test(passwordFieldOne.value)) {
tipOne.style.backgroundColor = 'red';
tipTwo.style.backgroundColor = 'gray';
tipThree.style.backgroundColor = 'gray';
} else if (passwordGradeTwo.test(passwordFieldOne.value)) {
tipOne.style.backgroundColor = 'red';
tipTwo.style.backgroundColor = 'orange';
tipThree.style.backgroundColor = 'gray';
} else if (passwordGradeThree.test(passwordFieldOne.value)) {
tipOne.style.backgroundColor = 'red';
tipTwo.style.backgroundColor = 'orange';
tipThree.style.backgroundColor = 'green';
}
} else {
passwordWarningOne.style.display = 'inline';
}
}, false);
// 密码确认判断
passwordFieldTwo.addEventListener('blur', function () {
if (passwordFieldTwo.value == '') {
passwordWarningTwo.style.display = 'inline';
passwordCorrect.style.display = 'none';
passwordWarningThree.style.display = 'none';
} else if (passwordFieldTwo.value == passwordFieldOne.value) {
passwordCorrect.style.display = 'inline';
passwordWarningTwo.style.display = 'none';
passwordWarningThree.style.display = 'none';
pwdBoolTwo = true;
} else if (passwordFieldTwo.value != passwordFieldOne.value) {
passwordWarningThree.style.display = 'inline';
passwordCorrect.style.display = 'none';
passwordWarningTwo.style.display = 'none';
}
}, false);
// 提交
submitBtn.addEventListener('click', function () {
if (userBool && pwdBoolOne && pwdBoolTwo) {
alert('信息填写正确');
} else {
alert('请填写正确的信息!');
}
}, false);
</script>
</body>
</html>
昨日之深渊,今日之浅谈。路虽远行则将至;事虽难做则可成。