选择符不仅可以使用到前后是确定的字符,还可以用到前后是表达式的
//原子表[]表示或的意思,()基本是表示一个整体
let reg = /[1232]/;
let reg = /(12|34)/
let hd = "12";
console.log(hd.match(reg))
//除换行外任何字符
/ \d+ . \d+ /
// /+符号,就真实表达/+符号
/ \d+ /. \d+ /
//在正则表达式中,需要双 // 来转义你的转义,
// s? 表示1个或0个
https?:\/\/\w+\.\w+\.\w/.test(url) \w 字母数字下划线
let price = '23.34'
// \d:0~9的数字 +:一个或多个数值
console.log(/\d+.\d+/.test(price)) // true 但是有问题,price = '23@34'还是true
// .换行外任何字符, .普通的点
console.log(/\d+\.\d+/.test(price)) // true 加了\对.进行转义 d也是普通字符串,加了\表示数值
let reg = new RegExp(/\d+\.\d+/) // true
//但是 reg = new RegExp('/\d+\.\d+/') 就不准确了,这相当于d+.d+了
reg = new RegExp('/\\d+\\.\\d+/') // true 准确了,使用了转义
console.log(reg.test(price))
let url = "https://www.wky.com"
console.log(/https?:\/\/\w+\.\w+\.+\w/.test(url)) // ?表示有s也许无s也行,//在正则中表示边界符,所以我们用\转义就成了\/\/
//www 任何字符,我们可以使用\w ; . 用 \.表示; wky 任何字符 \w ; . 用 \.表示;
判断用户输入是否为3-6位的字母:
<input name="user"></input>
<span></span>
<script>
document.
querySelector('[name="user"]').
addEventListener('keyup', function () {
// let flag = this.value.match(/[a-z]{3,6}/) // 只能输入3~6位的字母,但是有问题,只要超过3位都是成立
let flag = this.value.match(/^[a-z]{3,6}$/) // 加上边界限制就精确判断3~6位字母了
console.log(flag)
document.querySelector('span').innerHTML = flag ? "正确" : "错误"
})
/[a-z]{3,6}/ 表示取数组的前3-6位,超过也不影响
/^[a-z]{3,6}$/ 加了边界以后,就只能完全匹配,整个字符串只有3-6位,字符串完整性验证
let str = 'vzx23vgf32a'
console.log(/\d/.test(str)) // true \d代表数值 str中但凡有个数字就满足
console.log(/^\d/.test(str)) // false ^表示以数字开始; str = 3vgf就为true
console.log(/^\d$/.test(str)) // false ^表示以数字开始,$表示以数字结束; str = 2就为true
// /d+有的全统计上,不是搜到一个上报一个,/d是搜到一个上报一个
// /g是全局搜索
// \d : 数字 \D : 除了数字
// []里写的我都要,写啥要啥, 在[]里写^表示方括号里写的我都不要
// \s 空白 \S 除了空白
let str = 'syg35dd22'
console.log(str.match(/\d/)) // [ '3', index: 3, input: 'syg35dd22', groups: undefined ]
console.log(str.match(/\d\d/)) // [ '35', index: 3, input: 'syg35dd22', groups: undefined ]
console.log(str.match(/\d\d\d/)) // null
console.log(str.match(/\d/g)) // [ '3', '5', '2', '2' ]
console.log(str.match(/\d+/g)) // [ '35', '22' ] + 匹配一个或多个
let str = '张三:120-65625556; 李四:204-62681827'
console.log(str.match(/\d{3}-\d{8}/)) // ['120-65625556', index: 3, ......]
console.log(str.match(/\d{3}-\d{8}/g)) //[ '120-65625556', '204-62681827' ]
// \d : 数字 \D : 除了数字 + : 一个或多个
console.log(str.match(/\D/)) // [ '张', index: 0,.......]
console.log(str.match(/\D+/)) // [ '张三', index: 0,.......]
console.log(str.match(/\D/g)) // ['张', '三', ':','-', ';', '李', '四', ':', '-' ]
console.log(str.match(/\D+/g)) // [ '张三:', '-', ';李四:', '-' ]
str = '张三:120-65625556; 李四:204-62681827'
// []里写的我都要,写啥要啥
console.log(str.match(/[\d:;-]/g)) //[':', '1', '2', '0', '-', '6', '5', '6', '2', '5', '5', '5','6', ';', ':', '2', '0', '4', '-', '6', '2', '6', '8', '1', '8', '2', '7']
console.log(str.match(/[\d:;-]+/g)) //[ ':120-65625556;', ':204-62681827' ]
// 在[]里写^表示方括号里写的我都不要
console.log(str.match(/[^\d:;-]+/g)) //[ '张三', '李四' ]
// \s :空白
console.log(/\s/.test(' ')) //true
console.log(/\s/.test('\n')) //true 换行符
// \S 除了空白
console.log(/\S/.test('tew')) //true
console.log(/\S/.test(' ')) //false
console.log(/\S/.test(' bvcx ')) //true 因为它会往后继续找,找不是空白的就返回true了
// \w : 字母、数字、下划线 也就是说他囊括了 \d
let str = 'bhbs_sd23-v21v-'
console.log(str.match(/\d+/)) // [ '23', index:7 ,........]
console.log(str.match(/\w+/)) // ['bhbs_sd23', index: 0, ........]
console.log(str.match(/\w+/g)) // [ 'bhbs_sd23', 'v21v' ]
let email = '^&%[email protected]'
console.log(/\w+@\w+\.\w+/.test(email)) // true 这样不严谨, email = '126g%%……[email protected]'也为true
console.log(/^\w+@\w+\.\w+$/.test(email)) // false 因为加上了边界限定
// \W : 除了数字、字母、下划线
email = '^&%[email protected]'
console.log(email.match(/\W+/g)) // [ '^&%...', '@', '.' ]
// 用户名需求:以字母开始,后跟字母数字下划线,用户名长度在5~10位
console.log(/^[a-z]\w{4,9}$/.test('sdr7sw')) // true 因为[a-z]已经占了一位了,所以是{4,9}
// 用户名需求:以字母开始,后跟字母数字下划线和-,不区分大小写,用户名长度在5~10位
console.log(/^[a-z][\w-]{4,9}$/i.test('sdr7sw')) // true 因为[a-z]已经占了一位了,所以是{4,9}
// \d:数值 \w :数字字母下划线 . : 除了换行符之外的所有字符
let str = 'vsfc#%$ccsgc&v789.,.;。,'
console.log(str.match(/./)) // [ 'v', index: 0,.........]
console.log(str.match(/.+/)) // [ 'vsfc#%$ccsgc&v789.,.;。,', index: 0,inpu.....]
console.log(str.match(/.+/g)) //[ 'vsfc#%$ccsgc&v789.,.;。,' ]
// 需求:匹配一个网址
let net = 'https://www.baidu.com'
console.log(/https?:\/\/\w+\.\w+\.\w+/.test(net)) // true
//https直接写,s可有可无所以加? :直接写,//需要转义,\w+匹配一个或多个字母数字下划线,点(.)也需要转义...
// 需求:在一堆字符串中,找出里面的所有网址
net = 'https://www.baidu.com&Bbshbhttps://www.baidu.comGVV67https://www.baidu.com三个vhttps://www.baidu.com'
console.log(net.match(/https?:\/\/\w+\.\w+\.\w{0,3}/g)) // [ 'https://www.baidu.com', 'https://www.baidu.com', 'https://www.baidu.com', 'https://www.baidu.com' ]
// com只要3个字母,所以{0,3}
let str = `
vsfc#%$ccsgc
&v78-9
`
console.log(str.match(/.+/)) // ['vsfc#%$ccsgc', index: 1,...] 因为再遇到换行符他就停了
// \s:把相应字符串视为单行 相当于把换行符当作普通空白字符串来使用了 这样.也能匹配换行符了 .就无敌了!!!!
console.log(str.match(/.+/s)) // ['\nvsfc#%$ccsgc\n&v78-9 \n', index: 0,......]
let tel = '010 - 68762366'
console.log(tel.match(/\d+ - \d+/)) // ['010 - 68762366',index: 0,...]空格也是普通字符,只是我们人看不见,对计算机来说它和abc是一样的,我们可以直接写在正则中
// 但是也可以用\s来代替
console.log(tel.match(/\d+\s-\s\d+/)) // ['010 - 68762366',index: 0,...]
let str = 'wky'
// []:匹配str中满足[]条件的所有内容
console.log(str.match(/[sbahw]/)) // [ 'w', index: 0, inp.....]
// 不加[]表示完整的匹配一段内容
console.log(str.match(/sbahw/)) // null
let spanStr = `
https://www.wky.com
`
// \s:空白字符 \S:除了空白字符,[\s\S] : 所有字符 [\d\D]也行
console.log(spanStr.match(/[\s\S]+<\/span>/)) // [ '\nhttps://www.wky.com\n', index: 1, input: '\]
console.log(spanStr.match(/.+<\/span>/s))// [ '\nhttps://www.wky.com\n', index: 1, input: '\]
console.log(spanStr.match(/[/d/D]+<\/span>/s)) //如果不加 + 号,则只匹配一个就停了
let str = 'vzvSGfscf1F2'
console.log(str.match(/s/i)); // [ 'S', index: 3,...] /i不区分大小写
console.log(str.match(/f/g)); //[ 'f', 'f' ] /g全局匹配
console.log(str.match(/s/ig)); //[ 'S', 's' ] /ig不区分大小写且全局匹配 ig gi顺序随便
console.log(str.replace(/f/ig,'@')); //vzvSG@sc@1@2 将str中的f不区分大小写全都替换成@
// (\s*)表示连续多个空格的字符串 m 指的是每一行单独处理
let str = `
#1 js,22元 #
#2 java,0.345yuan #
#3 python,0.21 # wky
#4 node,2301 #
`
console.log(str.match(/^\s*#\d+\s+.+\s+#$/gm)); // [ '\n#1 js,22元 #', '\n#2 java,0.345yuan #', '\n#4 node,2301 #' ]
let res = str.match(/\s*#\d+\s+.+\s+#$/gm).map(item => {
item = item.replace(/\s*#\d+\s*/, '') // js,22元 # ; java,0.345yuan ; #node,2301 #
.replace(/\s+#/, '') // js,22元 ; java,0.345yuan ; node,230
console.log(item)
// 数组解构
let [name, price] = item.split(',') // item.split(','): [ 'js', '22元 ' ] ; [ 'java', '0.345yuan ' ].... ;
return { name, price } // 对象的key和value一样,简写
})
//sc={Han}会匹配到偏旁部首 片假字 /u 表示按unicode(utf-8)匹配(主要针对多字节比如汉字
//正则表达式 p {L} 匹配类别“字母”中的单个代码点。 p {N} 匹配任何脚本中的任何类型的数字字符
let str = `sbhhd我是中文sjb`
console.log(str.match(/\p{sc=Han}/ug)) // [ '我', '是', '中', '文' ]
let str = `sbhhd我是中文sjb`
console.log(str.match(/\w/)) // [ 's', index: 0, input: 'sbhhd我是中文sjb',...]
console.log(str.match(/\w/g)) // ['s', 'b', 'h','h', 'd', 's', 'j', 'b']属性丢失了
let reg = /\w/g // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // [ 's', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'b', index: 1, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 2, input: 'sbhhd我是中文sjb',
console.log(reg.lastIndex) // 3 所以每调用一次execlastIndex就会++
while(res = reg.exec(str)){
console.log('res: ', res);
}
// res: [ 'h', index: 3, input: 'sbhhd我是中文sjb', groups: undefined ]
// res: [ 'd', index: 4, input: 'sbhhd我是中文sjb', groups: undefined ]
// res: [ 's', index: 9, input: 'sbhhd我是中文sjb', groups: undefined ]
// res: [ 'j', index: 10, input: 'sbhhd我是中文sjb', groups: undefined ]
// res: [ 'b', index: 11, input: 'sbhhd我是中文sjb', groups: undefined ]
// g:当不是要找的值,直接跳过即可
// y:得一直连续的满足条件 y要连续才有效
let str = `hhh`
let reg = /h/y // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // [ 'h', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 1, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 2, input: 'sbhhd我是中文sjb',
console.log(reg.lastIndex) // 3 所以每调用一次execlastIndex就会++
str = `hhsahd`
reg = /h/y
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // [ 'h', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // [ 'h', index: 1, input: 'sbhhd我是中文sjb',
console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // [ 'h', index: 0, input: 'sbhhd我是中文sjb',
console.log(reg.lastIndex) // 1
// (.\d+)?:括号里内出现0或1次
let str = `我的qq号:6457412145,7465111,982333225,欢迎加入,网址:jhsbbnx.com`
let reg = /(d+),?/y // 不把正则提出来或不加g,exec永远获取到的都是s,不会往下走
console.log(reg.lastIndex) // 0
console.log(reg.lastIndex) // 0
console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // null
console.log(reg.exec(str)) // null
console.log(reg.lastIndex) // 0
//赋值
reg.lastIndex = 6
let arr = []
while(res = reg.exec(str)){
console.log(res)
arr.push(res[1])
}
console.log(arr); // [ '6457412145', '7465111', '982333225' ]
console.log(reg.exec(str)) //['6457412145,','6457412145',index:6....]
console.log(reg.exec(str)) // ['7465111,','7465111,',index:17....]
console.log(reg.exec(str)) // ['982333225,','982333225,',index:25....]
console.log(reg.lastIndex) // 35
data = '2022/10/1';
reg = /^\d{4}/\d{1,2}/\d{1,2}$/g
reg = /^\d{4}([-\/])\d{1,2}\1\d{1,2}$/g // ([-\/])以-作为分割或者/作为分割都行, \1 : 前一个以什么分割后一个也要一样,不能出现2020-10/1的格式
/^[a-z]\w{3,6}$/i
<input name="change" />
<script>
let input = document.querySelector(`[name="change"]`)
input.addEventListener('keyup', function () {
console.log(this.value.match(/^[a-z]\w{3,6}$/i))
})
</script>
let str = `2021vxfcx`
let reg = /[^vx]+/g // 除了vx其他的都匹配
console.log(str.match(reg)); // [ '2021', 'fc' ]
str = `张三:120-65625556; 李四:204-62681827`
reg = /[^:\d-;]+/g // 除了:数字 - ;其他的都要
console.log(str.match(reg)); // [ '张三', ' 李四' ]
普通初学者容易犯的错误:
str = `(张三:120-65625556); 李四:204-62681827`
let reg = /[()]+/g // 现在的()就是普通的字符串,没有原子组的含义了,除非把它放到[]的外面,点也一样,只是普通字符串
console.log(str.match(reg)); // [ '(', ')' ]
str = `
张三:120-65625556; 李四:204-62681827
`
let reg = /[\s\S]/g // .能匹配所有但不能匹配换行符,但/s/S真正的匹配所有
console.log(str.match(reg));// [ '\n', '张', '三', ':', '1', '2', '0', '-', '6', '5', '6', '2','5', '5', '5'...]
let str = `
vsahgvytdv
vsahgvytdv
`
let reg = /<(h[1-6])>([\s\S]*)<\/\1>/gi
// \s后面是{1,6},但是匹配的具体符号后面是[1,6],这容易混淆
// 前面有了原子表后面 才能用\1,表示和前面原子表的内容一样,
// reg = /<(h[1,6])>([\s\S])*<\/\1>/gi 也行
console.log(str.match(reg));// [ 'vsahgvytdv
' ]
let str = `https://www.baidu.com
http://wky.com
`
console.log(str.match(/https?:\/\/\w+\.\w+\.(com|cn|org)/g));
// // 需求:https:// 不要,只要域名,用括号把域名部分包起来 如下
console.log(str.match(/https?:\/\/(\w+\.\w+\.(com|cn|org))/g));
// //以上 0是整个内容 第一个出现的括号(是1,然后是2
// // 需求 去除第二个括号,让\2用不了:在括号里加(?: 如下
console.log(str.match(/https?:\/\/(\w+\.\w+\.(?:com|cn|org))/g));
// // 有些域名没有www 我们把www正则部分包起来,加? 修改正则如下
console.log(str.match(/https?:\/\/((\w+\.)?\w+\.(?:com|cn|org))/));
// ['https://www.baidu.com','www.baidu.com','www.',index: 0, input: 'ht...]
// 上面是从0开始数的,第0个表示匹配的完整的字符串,第一个是表示第一个(里匹配的内容,第二个是表示第二个(里匹配的内容 ; 所以下面while循环的时候,我们取res[1]
// 如果不想让他记录()的话,在()里加上?:即可 修改如下
console.log(str.match(/https?:\/\/((?:\w+\.)?\w+\.(?:com|cn|org))/)); // ['https://www.baidu.com','www.baidu.com',index: 0, input: 'htt...]
// 需求: 将str中所有域名都提出来
let urls = []
let reg = /https?:\/\/((?:\w+\.)?\w+\.(?:com|cn|org))/g // 不把reg提出来while循环就不会停。。。因为exec永远不会为null
while ((res = reg.exec(str))){
urls.push(res[1])
}
console.log(urls) // [ 'www.baidu.com', 'wky.com' ]
<input type="text" name="userPassword" />
// 需求:密码必须以字母或数字开头,不区分大小写,密码中必须包含至少一个大写字母和一个数字
<script>
let input = document.querySelector(`[name="userPassword"]`)
input.addEventListener('keyup', function (e) { // keyup:键盘抬起,mouseup鼠标抬起
let value = e.target.value // 拿到用户输入的值
let reg = [/^[a-z0-9]{5,7}$/i, /[A-Z]/, /\d/] // 密码必须以字母或数字开头,不区分大小写 ;密码中必须包含至少一个大写字母 ;密码中必须包含至少一个数字
let state = reg.every(item => item.test(value)) // 字符串必须满足reg中正则的所有条件才能返回true
console.log(state)
})
</script>
let str = `wkkkkky`
// +:表示一个或多个,加了问号就禁止贪婪,趋向于少的一方:一个,*:表示零个或多个,加了问号就禁止贪婪,趋向于少的一方:零个
console.log(str.match(/wk+/g)) // [ 'wkkkkk' ]
console.log(str.match(/wk+?/g)) // [ 'wk' ]
console.log(str.match(/wk*?/g)) // [ 'w' ]
console.log(str.match(/wk??/g)) // [ 'w' ] 禁止问号贪婪
console.log(str.match(/wk{2,}/g)) //[ 'wkkkkk' ]
console.log(str.match(/wk{2,}?/g)) //[ 'wkk' ] 趋向于2
//例子
<main>
<span>vxgsffstf</span>
<span>wky.com</span>
<span>nbsbsc.com</span>
</main>
<script>
let main = document.querySelector(`main`)
let reg = /([\s\S]+?)<\/span>/gi // 如果不加?就会把3个span一次性匹配完,而我们需要它一次匹配一个
main.innerHTML = main.innerHTML.replace(reg, (v, p1) => { // p1 第一个原子组所匹配的内容
return `有趣-
${p1}`
})
</script>
<body>
<div class="main">
<span>bhbudjsdx</span>
<span>wky.com</span>
<span>学正则</span>
</div>
</body>
<script>
const main = document.querySelector('.main')
let reg = /<(span)>([\s\S]+?)<\/\1>/g // 这里必须加?禁止贪婪,否则匹配就会超出span之外的
// console.log(main.innerHTML.match(reg)); //["bhbudjsdx\n wky.com\n 学正则"]
let res = main.innerHTML.matchAll(reg); //RegExpStringIterator {} 一个迭代对象
let contents = []
for (const item of res) {
contents.push(item[2]) // 如果是item[1],content就是["span", "span", "span"]
}
console.log('contents: ', contents); // ["bhbudjsdx", "wky.com", "学正则"]
</script>
const main = document.querySelector('.main')
let reg = /<(span)>([\s\S]+?)<\/\1>/g // 这里必须加?禁止贪婪
let contents = []
while (res = reg.exec(main.innerHTML)) {
contents.push(res[2])
}
console.log('contents: ', contents); // ["bhbudjsdx", "wky.com", "学正则"]
let str = `wkkkkky`
console.log(str.match(/w/g)) // [ 'w' ]
console.log(str.search(/w/g)) // 0 返回相应字符在字符串中的索引
let num = '(010)-44444444 (020)-99999999'
let reg = /\(\d{3,4}\)-\d{7,8}/g
console.log(num.match(reg)) // [ '(010)-44444444', '(020)-99999999' ]
reg = /\((\d{3,4})\)-(\d{7,8})/g
console.log(num.replace(reg,"$1-$2")); // 010-44444444 020-99999999
let msg = '%我要学习='
console.log(msg.replace('我要学习','$&')) [=我要学习=]
$` [%%=]
$' [%==]
// $只匹配内容 $& 匹配内容的的所有
// $` 表示匹配字符前面的内容
// $' 表示匹配字符后面的内容
.test
.exec
.+ .+?
断言:俗话的断言就是“我断定什么什么”,而正则中的断言,就是说正则可以指明在指定的内容的前面或后面会出现满足指定规则的内容,意思正则也可以像人类那样断定什么什么,比如"ss1aa2bb3",正则可以用断言找出aa2前面有bb3,也可以找出aa2后面有ss1.
零宽:就是没有宽度,在正则中,断言只是匹配位置,不占字符,也就是说,匹配结果里是不会返回断言本身。
//限定替换内容后面的内容
<!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>
<main>
学习是终身的事业,学习令你幸福
</main>
<script>
let main = document.querySelector("main");
let reg = /学习(?=是)/g;
main.innerHTML = main.innerHTML.replace(reg,`$&`)
</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>
<main>
学习是终身的事业,学习令你幸福
</main>
<script>
let main = document.querySelector("main");
let reg = /学习(?=是)/g;
main.innerHTML = main.innerHTML.replace(reg,`$&`)
</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>
<main>
<a href="https://baidu.com">百度</a>
<a href="https://yahoo.com">雅虎</a>
</main>
<script>
const main = document.querySelector("main");
const reg = /(?<=href=(['"])).+(?=\1)/gi;
main.innerHTML = main.innerHTML.replace(reg,"http://www.weixin.com")
</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>
let hd = 'jadfk0437jqd';
let res = /[a-z]+(?!\d+)/i; //此时达不到要求是因为没有限制结尾
let reg = /[a-z]+(?!\d+)$/i;//此时限制以字母结尾并且后面不是数字
console.log(hd.match(res));
console.log(hd.match(reg));
let msg = /^(?!.*张.*)[a-z]{5,8}$/i;//所有里面不能包含“张”
//语法:(?!pattern) 零宽负向先行断言
//作用:匹配非pattern表达式的前面内容,不返回本身。
//同样的 零宽负向后行断言
//语法:(?
//作用:匹配非pattern表达式的后面内容,不返回本身。
</script>
</body>
</html>