常用正则

143 阅读3分钟

正则

什么是正则

regular expression 描述了一种字符串匹配的模式,可以检查一个串首付含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串

  1. 匹配 2. 捕获

正则匹配方法

  • test exec 属于正则匹配捕获的方法
  • match是字符串常用的方法,以及字符串常用的 replace 方法

编写正则表达式

1. 创建正则有2中方式

// 字面量的方式创建 (两个斜杠之间包裹起来的,都是用阿里描述规则的元字符)
let reg1 = /\d+/;
// 构造函数模式创建
let reg2 = new RegExp("\\d+"); 
// 如果使用引号则需要转译,适用的场景是如果需要变量拼接
// 如以下情况,中间的type为变量时
// new RegExp("^@"+type+"@$");

2. 正则表达式有2部分组成

  • 元字符
  • 修饰符 文件后缀匹配
// 以data开头中间由字母、数字、下划线、的任意字符, 以.data后缀结尾
data(\w)?\.dat
// data (\w)? \.dat

3. 常用元字符

符号含义
*0 或 1 或 多次
+>= 0 0或多次
?0 或 1次
{n}n次
{n, }n到多次
{ n, m }n次到m次

4.常用元字符应用

  • 在 * 号 与+ 号后面加 ? 去掉贪婪模式
// 匹配数字
var str = "123456";
var reg = /[0-9]{1,4}/;
// 匹配标签
var str = "<h1>点匹配的是任意字符</h1>";
var reg = /<.*?>/
//此处使用问号去掉贪婪模式

5.分组的副作用

  • 会被缓存 ,使用 ?: 可以消除副作用
  • ?= 、?<= 、 ?! 、?< ! 问等 、问小等 、问叹 、问小叹
// 匹配数字前面的runoob, 显然最后一个就不符合条件
var str = "123456runoob123runoob456runoobIAM" 
var reg = /runoob(?=[\d+])/g;
str.match(reg); // ["runoob", "runoob"]

// 使用
var reg = (?![\d+])runoob;

6.特殊元字符

符号含义
\转义字符(普通 转 特殊 转 普通)
.除\n(换行符)以外的任意字符
以哪一个元字符开始
$以哪一个元字符结束
\n换行符
\d0-9 之间的数字[0-9]
\D非0-9之间的数字(大写与小写的意思是相反的)
\w数字、字母、下划线 [a-zA-Z0-9]
\W匹配非字母、数字、下划线。等价于[^a-zA-Z0-9_]
[0-9a-zA-Z_]匹配数字、字母、下划线与上面的相同
\s一个空白字符 (包含空格、制表符、换页符)
\t一个制表符(一个TAB键:四个空格)
x | y或者y其中的一个字符1| 2| 9
[xyz]x或者y或者z其中的一个字符, 多个字符中的任意一个字符
[^xy ]除了x/y以外的任意字符
[a-z]执行a-z这个范围中的任意字符
[^a-z]上一个取反的"非" , 在中括号中加^ 表示取非的意思
()正则中的分组
(?:)只匹配不捕获
\b匹配单词边界,即字与空格间的位置
\B非单词边界匹配
(?=)正向预查
(?!)负向预查

7.特殊元字符应用

以数字开头

var str = "123abc";
// + , 1或多个数字,abc结尾
var patt1 = /^[0-9]+abc$/; 
var patt2 = /^\d+abc$/;
str.match(patt1);

// 使用exec捕获数字开头,会出现只捕获第一个,会出现懒惰模式
var str = '2021-08-25';
var reg = /^\d+/;
reg.exec(str);
// ["2021", index: 0, input: "2021-08-25", groups: undefined]

以特定的字符开头结尾^$

let reg = /^\d/; //以数字开始
/^\d/.test("jiajia"); // false
/^\d/.test('888jiajia'); // false
let reg2 = /\d$/; // 以数字结尾
let reg3 = /^\d$/;
/^$\d+/.test(2332); // 只能是数字

replace时间格式化

  • 将2022-9-4转换成2022年9月4日
 const time = "2022-9-4";
 const reg = /^(\d{4})-(\d{1,2})-(\d{1,2})$/
 time = time.replace(reg,(...args) => {
     const [,$1,$2,$3] = args;
       $2.length < 2 ? $2 = "0" + $2 : null;
       $3.length < 2 ? $3 = "0" + $3 : null;
    return $1 + "年" + $2 + "月" + $3 + "日";
 })
  • 时间戳

邮箱匹配

  • 分组
const reg = /\w*((\.\w)|(\-\w))*@[a-zA-Z0-9]*((\.\w)|(\-\w))*\.[a-zA-Z0-9]*/

image.png

  • 不同分组的等价实现

// 不同的分组实际效果是等价的
const reg1 = ((\.\w+)|(\-\w+))
const reg2 = ((\.|-)[A-Za-z0-9]+)
const reg3 = ((\.|-)\w+)

// reg1 等价于reg2 跟reg3
  • ((.\w+)|(-\w+))

image.png

  • ((.|-)\w+)

image.png

  • ((.|-)[A-Za-z0-9]+)

image.png

  • 邮箱的简易实现
const emailReg = /[\w.%+-]+@[\w.-]+\.[a-zA-Z]{2,4}/

image.png

转化成驼峰形式

var str = "get-element-by-id";
function toCalceCase(str){
var reg = /[-_]\w/g;
    return str.replace((x) => {
        return x.slice(1).toUpperCase()
    })
}

单词边界\b

var str = "Chapter";
var reg = /ter\b/g;
// 则此时能匹配到
reg.exec(str); // ter
// 如果在单词的结尾加其他的单词则匹配不上
var str2 = "ChapterA";
reg.exec(str2); // 此时匹配不出任何结果

加千分位分隔符

var str = "1234567890";
var reg = /(?=(\d{3})+$)/
// ",123,456,789"
// 如何去掉第一个逗号呢? 使用负向预检,不匹配第一个 ?!^
reg = /(?!^)(?=(\d{3})+$)/g;

验证密码的合法性-(正向预检 ?=)

密码长度是6-12位,由数字、小写字母和大写字母组成,但必须至少包括2种字符

// 实现思路:
// 1. 密码长度是6-12位
// 2. 由数字、小写字符和大写字母组成
// 3. 必须至少包括2种字符
// 第一步写出条件1和条件2的正则
let regStep1 = /^[a-zA-Z\d]{6,12}$/
// 第二步 ,必须包含某种字符(数字、小写字母,大写字母)
let regStep2 = /?=.*\d/
// 第三步: 必须包含两种字符, 有四种排列组合方式
// 3.1 数字 + (大写字母 | 小写字母)
let reg1 = ((?=.*\d)|((?=.*[a-z])|(?=.*[A-Z]))
// 3.2 大写字母 | 小写字母
// 3.3 数字 + 大写字母 +小写字
  • 3.1 数字 + (大写字母 | 小写字母)

((?=.*\d)|((?=.* [a-z])|(?=.*[A-Z])))

image.png

  • 3.2 大写字母 + 小写字母

(?=.*[a-z])(?=.*[A-Z])

image.png

  • 3.3 大写字母 + 数字 + 小写字母

(?=.*[A-Z])(?=.*\d)(?=.*[a-z])

image.png

  • 最终综合(?=.*[a-z])(?=.*[A-Z])|(?=.*[A-Z])(?=.*\d)(?=.*[a-z])|^[a-zA-Z\d]{6,12}$

手机号3-4-4分割扩展-(负向预检 ?<=)

  1. 123 => 123
  2. 1234 => 123-4
  3. 12345 => 123-45
  4. 123456 => 123-456
  5. 1234567 => 123-456
  6. 12345678 => 123-4567-8
  7. 123456789 => 123-4567-89
  8. 12345678911 => 123-4567-8911
  • 第一步实现 123-4 如果使用正向预检,则 -1234,需要采用负向预检
const formatMobile = (mobile) => {
    return String(mobile).slice(11)
        .replace(/(?<=\d{3})\d+/, ($0) => '-' + $0)
}
  • 实现123-1234-
const formatMobile = (mobile) => {
    return String(mobile).slice(11)
        .replace(/(?=\d{3})\d+/, ($0) => '-' + $0)
        .replace(/(?<=[-\d]{8})\d{4}/, ($0) => '-' + $0)
}

查询字符串

// ?name=前端胖头鱼&"  "&b=2&"
function queryParams(url,name){
    // 以 [?&] ? 或则 & 字符开始 
    // name = 以&符开始的之间的 * 0-n个字符
    let reg = new RegExp(`[?&]${name}=[^&]*(?:&|$)`)
    let params = url.match(reg);
    reutrn params? decodeURIComponent(params[1]:'');
}

image.png

8.正则表达式常用的修饰符

i ignoreCase 忽略大小写 m multiline 可以进行多行匹配 global 全局匹配

学习工具:

正则字符匹配工具

正则分组工具

案例学习