js正则表达式
做字符串的增删改查
ant-design例子
:formatter="value => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
:parser="value => value.replace(/\$\s?|(,*)/g, '')"
简单的sample
常用的方法:
test:返回值是true或false
match:会返回匹配的字符组成的数组。若未匹配到则返回null。
let hd='jingdezhnejig23487669djiel2345';
let nums=[...hd].filter(item => {
return item>='0' && item<='9'
})
console.log(nums)
nums=[...hd].filter(item => {
return !Number.isNaN(parseInt(item))
})
console.log(nums)
console.log(hd.match(/\d/g))
创建正则表达式
字面量
不能使用变量,使用变量需要用eval
let hd='jingaghihecjijguirueit';
let a='u';
console.log(eval(`/${a}/g`).test(hd))
new RegExp
let pro = prompt('请输入要高亮的字符,支持正则')
let rg=new RegExp(pro,'g');
let titleDiv=document.querySelector('.title')
titleDiv.innerHTML=titleDiv.innerHTML.replace(rg,(search)=>{
return `<span style="color:red">${search}</span>`
})
—————————————————————————
选择符
首先,//正则表达式里面的是一个整体。那看的时候怎么去划分。
|:选择符。分道扬镳,左右两种
():分组。子表达式,整个表达式的一部分。
let tel='010-66666666';
// 1.这种问题在于:'010'也会匹配到,因为 | 划分开来了。
console.log(/010|021\-\d{8}/g.test(tel))
// 纠正方法:加上分组()
console.log(/(010|021)\-\d{8}/g.test(tel))
// 2.首尾还要加上^ &
console.log(/^(010|021)\-\d{8}$/g.test(tel))
[] 原子表 和 () 原子组
[]
[xxx]最后整个这里表达的是单个字符。[abcde]表达的是一种或的关系,(a|b|c|d)
只要字符出现在原子表中就匹配,这是可选的意思。
-
[]表达的是一种范围。[a-z],匹配小写字母,这里的 - 表达就是一种范围。[abcde]表达的就是a-e范围。
-
[]中的^符号表达的是取非的意思。比如,[^a-z]非小写字母。
-
[]中的特殊字符会被当做普通字符来看待。例如[(a)],会匹配(、a、)、这三个字符。
几个例子
// 是否全为英文
const str='';
/^[a-zA-Z]+$/.test(str);
// 是否包含英文
/[a-zA-Z]+/.test(str)
正则表达式(括号)、[中括号]、{大括号}的区别小结 - 安静的女汉纸 - 博客园
() 分组
第三章 正则表达式括号的作用_JavaAlliance-CSDN博客_正则表达式括号
获取(引用)分组
1.match
match返回的结果,在匹配到的情况下,第1个参数是整个匹配的结果,之后就是各个分组匹配到的内容。
2.RegExp.$1-$9
var regex=/(\d{4})-(\d{2})-(\d{2})/;
let dateStr='2021-11-26';
dateStr.match(regex);
console.log(RegExp.$1);
反向引用
引用之前匹配到的分组,就叫反向引用。
\1 匹配之前同样的那个字符,我要和它一样就是这个意思。\2 \3同理
var regex=/\d{4}(-|\/|\.)\d{2}\1\d{2}/; //下面有代码讲解
var string1="2017-06-12";
var string2="2017/06/12";
var string3="2017.06.12";
var string4="2016-06/12";
console.log(regex.test(string1)); // true
console.log(regex.test(string2)); // true
console.log(regex.test(string3)); // true
console.log(regex.test(string4)); // false
这里有一个很有意思的例子
var regex = /^((\d)(\d(\d)))\1\2\3\4$/; //下面有代码讲解
var string = "1231231233";
console.log( regex.test(string) ); // true
console.log( RegExp.$1 ); // 123
console.log( RegExp.$2 ); // 1
console.log( RegExp.$3 ); // 23
console.log( RegExp.$4 ); // 3
*有一个例外的情况,当引用的分组不存在时,\会对后面的字符进行转义。\1就表示对后面的1进行了转义。
var regex = /\1\2\3\4\5\6\7\8\9/; console.log( regex.test("\1\2\3\4\5\6\7\8\9") ); //true console.log( "\1\2\3\4\5\6\7\8\9".split("") );//下面有代码讲解
具体案例
首字母转换成大写
// 有几种方法
var regex=/\b[a-zA-Z]/g
var regex=/(?:^|\s)\w/g
var str='my name is lucy !'
const string=str.replace(regex,(c)=>{
return c.toUpperCase();
})
console.log(string);
// 还有一种做法
name = 'aaa bbb ccc';
uw=name.replace(/\b\w+\b/g, function(word){
return word.substring(0,1).toUpperCase()+word.substring(1);
});
// https://www.w3school.com.cn/jsref/jsref_replace.asp
转义
\通常表示转义
*题外话
用对象的方式,因为'\d'==='d',所以new RegExp('\\d+\\.\\d+'),可能需要多加一个斜杠。
字符有多个含义,把它转换一下
^ $ :限定边界
^:以xxx开始,限定开始边界
$:以xxx结束,限定结束边界
这是限定我们的边界。表示的是一种完全的严格的验证。
以下是一个例子:
如果不加^$,找到了就认为是成功了;
现在我们需要完全匹配,对整个字符串加以限定。用于进行完整性验证,否则就是部分验证。
<input type="text" name="user">
<span></span>
document.querySelector('input[name="user"]').addEventListener('keyup',function(){
console.log(this.value)
var reg=/^[a-zA-Z]{3,6}$/
var text=reg.test(this.value)?'正确':'错误'
document.querySelector('span').innerHTML=text
})
元字符
重复量词 表示数量的重复量词匹配的都是一连串的字符串,也就是一种贪婪匹配。
比如\d+
const str='houdunren 2021';
const reg=/\d+/g;
// +:一个或者多个
// 它这里一下就匹配到了4个
str.match(reg); // ['2021']
\d和\D
let str='houdunren 2021';
console.log(str.match(/\D+/g)); // ['houdunren ']
str=`
张三:010-88888888,李四:021-88888888
`
// 现在我们想匹配到中文
str.match(/[^:\d-,\s]+/g) // ['张三','李四']
\s和\S
\s表示空白字符:空格、tab、换行符、分页符,这些都是空白字符
\w和\W
这里有一个匹配用户名的例子
需求:以字母开头,后跟字母、数字、下划线,5-10位
综合来使用:结合穷糊匹配,禁止贪婪,模式修正符,断言匹配
const str='8houdunren';
const reg=/^[a-zA-Z]\w{4,9}$/;
console.log(reg.test(str));
点元字符 .
-
点元字符:任意字符(除了换行符)。所以你想单纯匹配点就要转义\
let str='https://wetest.qq.com'
let reg=/^https?:\/\/\w+\.\w+\.\w+$/
console.log(str.match(reg))
-
但是它无法匹配换行符
s模式:视为单行模式。将换行符当成普通空白来使用。
let hd=`
houdunrencom
houdun
`
console.log(hd);
console.log([...hd]);
console.log(hd.match(/.+/g));
console.log(hd.match(/.+/s));
额外:空格在正则中是普通字符,在正则中直接敲空格就行,或者用\s。
匹配任意一个字符
这种表达方式很巧妙,\s表示的空白,\S表达的是非空白,它们是取非的关系。那我[\s\S]不就表达的是任意字符了么。[\s\S] [\d\D]
let hd=`
<span>
houdunrencom @@@@@
houdun
</span>
`
console.log([...hd]);
console.log(hd.match(/<span>[\s\S]+<\/span>/));
表达的范围从小到大:a \d \w . [\s\S]
i与g模式修正符
模式修正符:把正则表达式的运行方式发生改变
/i:忽略大小写。例如邮箱和网址大写也是可以的
/g:全局。贪婪
m模式
这个例子稍微有点复杂
-
/m:首先多行模式。把每一行单独提取出来匹配,m多行模式主要是针对^$起作用,让它匹配到每一行的头和尾,因为如果不设置/m的话,一个字符串无论是否换行只有一个开始^和结尾$。一个大字符串需要每一行单独处理的时候用m模式就非常合适。
-
然后是另外一个细节的点,要注意行首和行尾的空格,有必要时加入\s*
let hd=`
#1 js,200元 #
#2 php,300元 #
#91 houdunren.com # 后盾人
#3 node.js,180元 #
`
console.log([...hd]);
// console.log(hd.match(/\s*#\d+\s+.+\s+#\s+/g))
// 这里尤其要注意行首行尾的\s*
console.log(hd.match(/^\s*#\d+\s+.+\s+#$/gm))
let lines = hd.match(/^\s*#\d+\s+.+\s+#$/gm);
let lessons=lines.map(line=>{
console.log(line)
console.log('line.match===')
console.log(line.match(/\s*#\d+\s+(.+),(.+)\s+#/))
let [,name, price]=line.match(/\s*#\d+\s+(.+),(.+)\s+#/);
// 还有一种方法是使用replace,把头和尾都替换成''
// let [name,price]=
// line.replace(/\s*#\d+\s+/,'').replace(/\s+#/,'').split(',')
return {name,price}
})
console.log('lessons:')
console.log(lessons)
u模式
这里涉及到了很多字符编码的知识点。
【转】正则表达式(三):Unicode诸问题(下)_carvin_happy的专栏-CSDN博客
前端js正则\p的使用, 全局标志g的问题_王为仁的博客-CSDN博客
字符编码笔记:ASCII,Unicode 和 UTF-8 - 阮一峰的网络日志
彻底弄懂 Unicode 编码_hezh1994的博客-CSDN博客_unicode编码
其实这里都是unicode编码的知识。
\p都需要结合/u模式一起来使用
\p{L}:表示字母
\p{N}:表示数字
\p{P}:匹配标点符号
还有它的unicode script属性,可以区分不同国家的语言
let hd=`houdunren2010.不断发布教程,加油!英文标点!`
console.log(hd.match(/\p{P}/gu))
console.log(hd.match(/\p{sc=Han}/gu))
还有一个要注意的:如果遇到宽字节,也就是4个字节的,也需要加上/u
lastIndex与exec方法
exec方法的优势就是能够记录每一个匹配字符串的详细信息,它的原理是改变lastIndex。
获取每一个主信息
var str="I love antzone ,this is animate";
var reg=/an/;
console.log('非全局-----------');
console.log(str.match(reg));
console.log('-----------');
console.log(reg.lastIndex);
console.log(reg.exec(str));
console.log(reg.lastIndex);
reg=/an/g;
console.log('全局-----------');
console.log('match-----------');
console.log(reg.lastIndex);
console.log(str.match(reg));
console.log(reg.lastIndex);
console.log('exec-----------');
console.log(reg.lastIndex);
console.log(reg.exec(str));
console.log(reg.lastIndex);
console.log(reg.exec(str));
console.log(reg.lastIndex);
console.log('while-----------');
reg.lastIndex=0;
console.log(reg.lastIndex);
let mat=[]
while(mat=reg.exec(str)){
console.log(mat);
}
js正则表达式之exec方法讲解_uwenhao2008的博客-CSDN博客_正则exec
y模式
lastIndex只在g模式和y模式下有效果,其他的情况这个lastIndex其实是被完全忽略掉了。只有g模式和y模式会读取并更新lastIndex的值。
y模式和g模式的区别:g模式会跳过不匹配的字符串,继续向后搜索;而y模式,只要lastIndex当前位置字符串不匹配,就会立马停止不会再继续向后搜索了。那这个就是两者表现上的区别。y 模式表示匹配到不符合的就停掉,不会继续往后匹配,必须连续的符合条件的。
而从语法上来讲,y模式改变了^字符的含义,不再表示整个字符串的开始位置,而是当前的偏移位置。
var re = /^./y;
console.log(re.test("foo")); //true
console.log(re.lastIndex); //1
console.log(re.test("foo")); //true
console.log(re.lastIndex); //2
JavaScript:正则表达式的/y标识 - 紫云飞 - 博客园
作用:让我们匹配大字符串的时候效率更高
let hd=`后盾人QQ群:6666666666,8888888888,9999999999后盾人不断分享视频教程,后盾人网址是 www.houdunren.com`
let reg=/(\d+),?/y
let res;
console.log('---')
reg.lastIndex=7
let qq=[]
while(res=reg.exec(hd)){
console.log(res)
qq.push(res[1])
}
console.log('qq')
console.log(qq)