正则表达式学习

  |  

常用元字符

表达式 介绍
/…/ 代表一个模式的开始和结束
^ 匹配字符串的开始,仅限在/…/中,在[]代表非
$ 匹配字符串的结束
\s 匹配任意空白字符
\d 匹配任意数字,相当于[0-9]
\w 匹配一个数字 字符串 下划线的字符,相当于[A-Za-z0-9_]
. 除了换行符的任意字符

常用反义字符

表达式 介绍
\S 匹配任意不是空白字符
\D 匹配任意不是数字的字符,相当于[^0-9]
\W 匹配一个不是数字 字符串 下划线的字符,相当于[^a-za-z0-9_]
[^a] 匹配不是 a 的其他字符

常用限定符

表达式 介绍
{n} 匹配前一项 n 次
{n,} 匹配前一项>=n 次
{n,m} m>=匹配前一项>=n 次
* 相当于{0,}
+ 相当于{1,}
? 相当于{0,1}

懒惰限定符

表达式 介绍
*? 重复任意次,但尽可能少重复
+? 重复 1 次或者更多次,但尽可能少重复
?? 重复 0 次或 1 次,但尽可能少重复
*? 重复任意次,但尽可能少重复
{n,m}? 重复 n 到 m 次,但尽可能少重复
{n,}? 重复 n 次以上,但尽可能少重复

常用分组语法

表达式 介绍
(exp) 匹配 exp,并捕获文本到自动命名的组里
(?<name>exp) 匹配 exp,并捕获文本到名称为 name 的组里,也可以写成(?’name’exp)
(?:exp) 匹配 exp,不捕获匹配的文本,也不给此分组分配组号
(?=exp) 匹配 exp 前面的位置
(?<=exp) 匹配 exp 后面的位置
(?!exp) 匹配后面跟的不是 exp 的位置
(?<!exp) 匹配前面不是 exp 的位置
(?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

练习

基础

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//连续3个数字
var pattern1 = /\d{3}/g;
console.log(pattern1.test('s23')); // false
console.log(pattern1.test('s112s')); // true

//连续2个相同的 数字
var pattern1 = /(\d)\1/g;
console.log(pattern1.test('s23')); // false
console.log(pattern1.test('s223s')); // true

//连续3个相同的数字
var pattern1 = /(\d)\1{2}/g;
console.log(pattern1.test('s23')); // false
console.log(pattern1.test('s222s')); // true

//连续3个或3个以上 相同的 字符
var pattern1 = /(\w)\1{2,}/g;
console.log(pattern1.test('s23')); // false
console.log(pattern1.test('saaaa2s')); // true

//正整数
[1-9]\d*

//负整数
-[1-9]\d*

//整数
(-?[1-9]\d*)|0

//正浮点数
\d+.\d+

//负浮点数
-\d+.\d+

//浮点数
-?\d+.\d+

//中文字符
[\u4e00-\u9fa5]

//双字节中文字符
[^\x00-\xff]

//空格
\s

//换行
\n

^ 和 $ 的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//假如我把 正浮点数 的正则写成这样 :(0.\d+)|(\d+.\d+) ,现在开始匹配

//匹配一个字符串中的 正浮点数
var pattern = /(0.\d+)|(\d+.\d+)/;
console.log(pattern.test('0')); // false
console.log(pattern.test('0.5')); // true
console.log(pattern.test('a0.5')); // true
console.log(pattern.test('a0.5s')); // true
console.log(pattern.test('a0.a5s')); // false

//匹配以 `正浮点数` 开头或结尾 的字符串
var pattern = /^(0.\d+)|(\d+.\d+)$/;
console.log(pattern.test('0.5')); // true
console.log(pattern.test('a0.5')); // true
console.log(pattern.test('a0.5s')); // false
console.log(pattern.test('a0.a5s')); // false

//只匹配 正浮点数
var pattern = /^(0.\d+)$|^(\d+.\d+)$/;
//或 /^((0.\d+)|(\d+.\d+))$/
console.log(pattern.test('0.5')); // true
console.log(pattern.test('a0.5')); // false
console.log(pattern.test('a0.5s')); // false
console.log(pattern.test('a0.a5s')); // false

格式日期

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//只匹配 日期格式:年-月-日
var pattern7 = /^\d{4}-(1[0-2]|0?[1-9])-(0?[1-9]|[12]\d|3[01])$/;
console.log(pattern7.test('ad2016-08-20ad')); // false
console.log(pattern7.test('2016-08-20')); // true
console.log(pattern7.test('2016-8-20')); // true
console.log(pattern7.test('16-08-20')); // false
console.log(pattern7.test('2016/08/20')); // false
//若去掉^和$
var pattern7 = /\d{4}-(1[0-2]|0?[1-9])-(0?[1-9]|[12]\d|3[01])/;
console.log(pattern7.test('ad2016-08-20ad')); // true

//只匹配 日期格式:年-月-日 或 年.月.日 或 年/月/日
var pattern7 = /^\d{4}(\/|\-|.)(0?[1-9]|1[0-2])\1(0?[1-9]|[12]\d|3[0-1])$/
console.log(pattern7.test('ad2016-08-20ad')); // false
console.log(pattern7.test('2016-08-20')); // true
console.log(pattern7.test('2016/08/20')); // true
console.log(pattern7.test('2016.8.20')); // true
console.log(pattern7.test('2016-08-9')); // true
console.log(pattern7.test('2016/18/20')); // false

时间

1
2
3
4
5
//只匹配  时间格式:小时:分钟, 24小时制
var pattern8 = /^((0?|1)\d|2[0-3]):([0-5]\d)$/;
console.log(pattern8.test('13:45')); // true
console.log(pattern8.test('3:45')); // true
console.log(pattern8.test('13点45')); // false

身份证号

1
2
3
4
5
6
//只匹配 中国大陆身份证号,15位或18位
var pattern9 = /^\d{15}|\d{17}[\d|X]$/;
//或 /^\d{15}(\d{2}[0-9X])?$/
console.log(pattern9.test('15020416803082111X')); //true
console.log(pattern9.test('422322199901090033')); // true
console.log(pattern9.test('asdfasdfasfasdf123')); // false

手机号 QQ 号 用户名

1
2
3
4
5
6
7
8
9
10
11
//只匹配 用户名
^[A-Za-z0-9_\/-\u4e00-\u9fa5]+$

//只匹配 长度为8-10的用户密码(以字母开头、数字、下划线)
^[A-z\_]\w{7,9}$

//只匹配 QQ号
^[1-9](\d{5,11})$

//只匹配 手机(国内)
^0?(13|14|15|17|18|19)[0-9]{9}$

注:
1、合并:
0?[0-9]|1[0-9]可以合并为(0?|1)[0-9]
\d{4}|\d{2} 不能合并为\d({2}|{4}); //因为{N}代表次数
2、化简:
[0-9] 化简写为 \d
[A-Za-z0-9]化简写为 [A-z0-9]
3、. 是 \w\s效果的累加
如果要打印. 、$、 /等,都要加转义字符:\.、\$、\/

面试练习题

匹配字符串中所有的 HTML(1)标签头部 或 尾部 (2)标签头部(3)完整标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var str = 'ada<option value="hh">0</option>54<div id="as">adda</div>ad'
var result = str.match(/<.*>/g);
console.log(result); //["<option value="hh">0</option>54<div id="as">adda</div>"]

//(1)匹配 标签头部 或 尾部
var result = str.match(/<.*?>/g);
console.log(result); //["<option value="hh">", "</option>", "<div id="as">", "</div>"]

//(2)匹配 标签头部
var result2 = str.match(/<[A-z].*?>/g);
console.log(result2);// ["<option value="hh">", "<div id="as">"]

//(3)匹配 完整标签
var result3 = str.match(/<[A-z].*?>.*?<\/.*?>/g);
console.log(result3);// ["<option value="hh">0</option>", "<div id="as">adda</div>"]

写出正则表达式, 从一个字符串中提取所有链接地址。

1
2
3
4
var str = 'IT面试题博客中包含很多<a href="http://hi.baidu.com/mianshiti/blog/category/微软面试题">微软面试题</a>';
var exg = /<a(?: [^>]*)+href="(.*)"(?: [^>]*)*>/g;
console.log(exg.exec(str)[1]);
//http://hi.baidu.com/mianshiti/blog/category/微软面试题

如何获取一个字符串中的数字字符,并按数组形式输出

1
2
var str = 'dgfhfgh254bhku289fgdhdy675gfh';
console.log(str.match(/\d+/g)); //["254", "289", "675"]

敏感词过滤

1
2
3
var str = '我草你妈哈哈背景天胡景涛哪肉涯剪短发欲望';
var result = str.replace(/草|肉|欲|胡|景|涛/g,'*');
console.log(result); //我*你妈哈哈背*天***哪*涯剪短发*望

判断是否符合 USD 格式

在这里插入图片描述

1
2
3
4
5
6
var pattern7 = /^\$\d{1,3}(,\d{3})*(\.\d{2})$/;
console.log(pattern7.test('$1,023,032.03')); // true
console.log(pattern7.test('$2.03')); // true
console.log(pattern7.test('$3,432,12.12')); // false
console.log(pattern7.test('$34,344.3')); // false
console.log(pattern7.test('da$2.03')); // false

给定字符串 str,检查其是否以元音字母结尾。

元音字母包括 a,e,i,o,u,以及对应的大写;若包含则返回 true,否则返回 false

1
2
3
4
5
6
function endsWithVowel(str) {
return (/[a,e,i,o,u]$/i).test(str);
}
console.log(endsWithVowel('gorilla')); //true
console.log(endsWithVowel('gorillE')); //true
console.log(endsWithVowel('gorillx')); //false

驼峰式字符串 borderLeftColor 和 连字符式字符串 border-left-color 相互转换

1
2
3
4
5
6
7
var str = 'borderLeftColor';
var str2 = 'border-left-color';

///把str换成 连字符式
console.log(str.replace(/[A-Z]/g, (item) => '-' + item.toLowerCase())); //border-left-color
//把str换成 驼峰式
console.log(str2.replace(/-([a-z])/g, (item, $1) => $1.toUpperCase())); //borderLeftColor

对人口数字的格式化处理,三位数字用一个’,’(逗号)隔开

1
2
3
4
5
function numberWithCommas(x) {
//对右侧人口数字的格式化处理,三位数字用一个','(逗号)隔开
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
}
console.log(numberWithCommas(12345678))//12,345,678

去掉 http 协议的 jpg 文件的协议头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var imgs = [
'http://img.host.com/images/fds.jpg',
'https://img.host.com/images/fjlj.jpg',
'http://img.host.com/images/djalsdf.png',
'https://img.host.com/images/adsjfl.png',
'http://img.host.com/image/jasdlf.jpg'
];
var result = imgs.map((img)=>{
return img.replace(/http:(\/\/.+\.jpg)/,(item,$1) => {
return $1
});
});
console.log(result);

// ["//img.host.com/images/fds.jpg",
// "https://img.host.com/images/fjlj.jpg",
// "http://img.host.com/images/djalsdf.png",
// "https://img.host.com/images/adsjfl.png",
// "//img.host.com/image/jasdlf.jpg"]

找出数组中的表示日期的时间字符串,并修改格式为‘月-日-年’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var times= ['2006/02/03',
'test/07/sd',
'2016/05/10',
'1998-03-07',
'12345/23/45678',
'1234/23/56789',
'12345/23/45']
let list = [];
times.map(time => {
return time.replace(/^(\d{4})[/-](\d{2})[/-](\d{2})$/, (match, $1, $2, $3) => {
list.push(`${$1}-${$2}-${$3}`);
});
});
console.log(list);

// [ '2006-02-03', '2016-05-10', '1998-03-07' ]

获取 url 中的参数

指定参数名称,返回该参数的值 或者 空字符串

不指定参数名称,返回全部的参数对象 或者 {}

如果存在多个同名参数,则返回数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//    获取 url 参数
function getUrlParam(sUrl, sKey) {
var arr={};
sUrl.replace(/\??(\w+)=(\w+)&?/g,function(match,p1,p2){
//console.log(match,p1,p2);
if(!arr[p1]){
arr[p1]=p2;
}
else {
var p=arr[p1];
arr[p1]=[].concat(p,p2);
}
})
if(!sKey)return arr;
else{
for(var ele in arr){
if(ele==sKey){return arr[ele];}
}
return "";
}
}

让字符串制定部分变色

让页面中这段字符串 “我爱你哈哈爱你” 中的”爱“字全变为红色。

1
2
3
4
5
6
<div id="as" >我爱你哈哈爱你</div>

var oDiv = document.getElementById('as');
var str = oDiv.innerHTML;
var newStr = str.replace(/爱/g, m => "<span style='color:red'>" + m + "</span>");
oDiv.innerHTML = newStr;

常用正则

  1. email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/

  2. url: new RegExp('^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', 'i')

  3. hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i

文章目录
  1. 1. 常用元字符
  2. 2. 常用反义字符
  3. 3. 常用限定符
  4. 4. 懒惰限定符
  5. 5. 常用分组语法
  6. 6. 练习
    1. 6.1. 基础
    2. 6.2. ^ 和 $ 的使用
    3. 6.3. 格式日期
    4. 6.4. 时间
    5. 6.5. 身份证号
    6. 6.6. 手机号 QQ 号 用户名
  7. 7. 面试练习题
    1. 7.1. 匹配字符串中所有的 HTML(1)标签头部 或 尾部 (2)标签头部(3)完整标签
    2. 7.2. 写出正则表达式, 从一个字符串中提取所有链接地址。
    3. 7.3. 如何获取一个字符串中的数字字符,并按数组形式输出
    4. 7.4. 敏感词过滤
    5. 7.5. 判断是否符合 USD 格式
    6. 7.6. 给定字符串 str,检查其是否以元音字母结尾。
    7. 7.7. 驼峰式字符串 borderLeftColor 和 连字符式字符串 border-left-color 相互转换
    8. 7.8. 对人口数字的格式化处理,三位数字用一个’,’(逗号)隔开
    9. 7.9. 去掉 http 协议的 jpg 文件的协议头
    10. 7.10. 找出数组中的表示日期的时间字符串,并修改格式为‘月-日-年’
    11. 7.11. 获取 url 中的参数
    12. 7.12. 让字符串制定部分变色