javascript 正则表达式的一些总结

正则表达式是匹配模式,要么匹配字符,要么匹配位置。请记住这句话
(?=p) 就与 ^ 一样好理解,就是 p 前面的那个位置
单词边界的一个认识
\b 是单词边界,具体就是\w与\W之间的位置,也包括\w与 ^ 之间的位置,和\w与$之间的位置。

正则表达式,零宽断言.零宽断言的括号不会被纳入捕获中
                   /*开头处非右,开头处始终不存在逗号*/                   
"457347674837".replace(/(?=(...)+$)(?!^)/g, ',')
//每三个数字之间加一个, 并且开头没有逗号
正预测:(?=expr) 断言某个位置的右边满足expr
负预测:(?!expr) 断言某个位置的右边 不 满足expr
//表示引号之外的,全部替换成|
'foo,bar,"abc,def",a,b,"x,y,z",baz,baa'.replace(/(?=([^"]*"[^"]*"[^"]*)*$|[^"]*$),/g,'|')
(/(?=([^"]*"[^"]*"[^"]*)*$|[^"]*$),/g,'|')//|之前为考虑到一个引号都没有的情况
//开头的右边起,非引号的字符若干个,引号字符一个,非引号字符若干个,引号字符一个,非引号字符若干个.(xxx"xxx"xxx)* 的 逗号 xxx*$表示0-N次 以这个方式结束的逗号
//或者从开头起的非(没有一个引号)引号字符 的逗号
  //*这些内容全部是在捕获位置,实质更换的是*/ 
(/(?=([^"]*"[^"]*"[^"]*)*[^"]*$),/g,'|')
//一个引号都不出现的情况 或者引号结束之后的情况([^"]*$)其他字符可0-n  
//(xxx*"xxx*"xxx*)*xxxx*$ 这个情况 
(/(?=([^"]*"[^"]*")*[^"]*$),/g,'|')
//简化版本,表达为(xxx*"xxx*"xxx*)*xxxx*$
(/(?=(([^"]*"){2})*[^"]*$),/g,"|")
//(xxx*"){2}这个位置出现两次
(?=(([^"]*"{2})*[^"]*$)
正常的括号不想被捕获到的时候,用(?:)
'foobar'.match(/o(b)/)
=>["ob", "b", index: 2, input: "foobar"]

'foobar'.match(/o(?:b)/)
=>["ob", index: 2, input: "foobar"]

new RegExp('')
=>/(?:)/

后向引用
/(expr)\1/ 其中\l表示前面(expr)捕获到的具体内容,以此类推:反/后向引用
^$ \b //\1既为出现过的前一项重叠
'张三 张三三 李四 李四四 王五 王五五'.replace(/.(.)\1/g,"重叠的替换")
=>"张三 重叠的替换 李四 重叠的替换 王五 重叠的替换"
分组后面有量词的话,分组最终捕获到的数据是最后一次的匹配。
/(\d)+/.exec('12345')
(2) ["12345", "5", index: 0, input: "12345"]

此时得\1就是5
/(\d)+...\1/.test('12345   5')
/(\d)+...\1/.exec('123456   6')
(2) ["123456   6", "6", index: 0, input: "123456   6"]

可以用这种写法在js里模拟回顾型零宽断言
(?=expr1)(?:expr1)(?=expr2)
"barbazfoo".replace(/((?=bar)(?:bar)(?=ba))(b)/g,"啊")
=>"啊azfoo"//开头的右边,隔了需要找到字符的字符个数,下一项的前面 可以全部更换
"barbazfoo".replace(/((?=bar)(?:bar)(?=ba))/g,"啊")
=>"啊bazfoo"//锁定第一项相同的字符之后,全部都要换掉,不锁定则取代第一项

String.raw`xxxx`函数接收内容也是一个数组,因为可以插值 插值之后通过${}将字符串分割
function r(arg){
  return arguments
}
rr`\\aa${5}\\bb${45}`
实质接收的参数:
arguments[0]: ["\aa", "\bb", "", raw: Array(3)]
raw:["\\aa", "\\bb", ""]//为未转义的结果 字面量
arguments[1]:5
          2 :45
正则表达式中raw函数的实现
模板字符串在控制台打印出来是双引号


模板字符串 `aa{1}bb{2}cc{3}dd`
分成了四个部分 即:aa,bb,cc,dd 
function raw(parts,...inserts){//parts接收的是字符串被分割后.(...inserts)接收的是插入的数字 part是插入下标
  return parts.raw.reduce((res,part,i)=>{
    return res+inserts[i-1]+part
  })
}
raw属性是一个数组,第0项是直接书写的内容
String.raw`xxxx`函数接收内容也是一个数组,因为可以插值 即上部分的函数表达式
`\\`不返回,因为系统会认为(\`)` //是转义未完成 没有结束
//search通过正则找字符串中的内容,只能从开始位置去找,不能定义位置

//自制search封装函数 可以选择性的去查找

String.prototype.search2=function(re,startIndex){
  re=new RegExp(re,'g')//构造一个正则,加上g
  re.lastIndex=startIndex//赋值给re的lastinde属性上去
  return re.exec(this) //改变了这个正则的re属性
}
//用模板字符串直接构造正则
new RegExp(String.raw` 内容 `) 
要匹配'a' '-' 'z'符号
不能写成[a-z]
应该写成 [-az] [az-] [a\-z] 放在开头或者结尾 或者转义
\s 表示 [ \t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页
符。
表示匹配任意字符:可以使用 [\d\D]、[\w\W]、[\s\S] 和 [^] 中任何的一个。
|字符 分支结构也是惰性的

匹配时间 24小时制是四位数 00:00 每一位进行限定
/^([01][0-9])|[2][0-3]:[0-5]|[0-9]$/.
如果也要求匹配 "7:9",也就是说时分前面的 "0" 可以省略。
/^(0?[0-9]|1[0-9]|[2][0-3]):(0?[0-9]|[1-5][0-9])$/
匹配日期
/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]$)/
匹配文件夹
盘符:\文件夹\文件夹\文件夹\
/^[a-zA-Z]:\\([^\\:*<>|"?\r\n/]+\\)*([^\\:*<>|"?\r\n/]+)?$/
                         避免出现特殊符号

匹配id
/id=".*"/
 /id="[^"]*"/
\m 用法 
var result = "I\nlove\njavascript".replace(/^|$/gm, '#');
console.log(result);
/*
#I#
#love#
#javascript#
*/
/((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[AZ]))^[0-9A-Za-z]{6,12}$/
同时包含数字和小写字母
• 同时包含数字和大写字母
• 同时包含小写字母和大写字母
• 同时包含数字、小写字母和大写字母
• 以上的 4 种情况是或的关系(实际上,可以不用第 4 条)。
非贪婪模式为了整体匹配成,也会尽可能的贪婪的匹配 但是不会捕获(存在回溯现象)
正则表达式的优先级符号
一级:转义符
\
二级:括号和方括号
(...)(?:...)(?=...)(?!...)[...]
三级:量词限定符
{m}{mn}{m,}?*+
关于问号:
*? 重复任意次,但尽可能少重复
+? 重复1次或更多次,但尽可能少重复
?? 重复0次或1次,但尽可能少重复
{n,m}? 重复n到m次,但尽可能少重复
{n,}? 重复n次以上,但尽可能少重复
四级:位置和序列
^$ \元字符 一般字符
管道符:
|
所谓元字符,就是正则中有特殊含义的字符。
所有的元字符全部可以转义


一些练习题

1,将信用卡的前面的数字若干位变成###只留下后四位数字
//63124655897=>*******5897
function chage(cc){
return cc.replace(/.(?=....)/g,'#')
}
//使用零宽断言,一个字符的右边必须有四个字符,将这四个字符之前的全部字符换成#
其他思路
function chage(cc){
return  cc.slice(0,-4).replace(/./g,'#')+cc.slice(-4)
}//cc.slice(0,-4)搜索到从0-倒数第四个元素位置,将其搜索出来全部替换成#再拼接上字符串后四位
function chage(cc){
  return cc.replace(/(?=.....)./g,'#')
}//先找到位置,再确定字符

2,前面第一个字母是编码,其单词的其他字母位置为反方向.
function reve(str){
  return num.replace(/(\d+)(\w*)/g,(m,code,rest)=>{
    return String.fromCharCode(+code/*字符串变数字再变成字符*/)+rest.split('').reverse().join('')
  })//字符串变数组再倒叙,再变回字符串再与前面转义后的字符相加
}
eg:'72olle 103doo 100ya'
=> 'hello good day'
再把结果反转回去
function reveve(str){
  return str.replace(/(\w)(\w*)/g,(_,first,rest)=>{
    return first.charCodeAt(0)+rest.split('').reverse().join('')
  })//捕获到第一个单独的字符(以及后面的字符)把第一个字符转换成编码,再倒序后面的字母,拼接.
}
3,前面第一个字母是编码,将第二个字符与最后一个字符互换了
function decipherThis(str) {
  return str.replace(/\b(\d+)(\w)?(\w*?)(\w)?\b/g, (m, code, a,b,c) => {
    return String.fromCharCode(+code) + (c||'') + (b||'') + (a||'')
  })
};
4,删除所有单词右边的'!'
function x(str){
  return str.replace(/(\w)(!*)(?= |$)/g,'$1')
}//捕获到i以及后面若干个!,结束的情况存在空格或者结束,全部这位置的所有i和!全部替换成i
eg:"Hi! Hi!".replace(/(\w)(!*)(?= |$)/g, '$1')
   "Hi Hi"
其他思路
function remove(s){
  //coding and coding....
  return s.replace(/!*( |$)/g, '$1')
}//遇见的若干!全部换成空格或者结束(空的)
function remove(s){
  return s.replace(/\b!+/g,'')
}//单词边界处的所有叹号 全部换成空

5,字符串是一个细胞,晚期的是C,初期的是c,常规细胞是小写字母,重要细胞是大写.
要求:重要细胞不能被剪掉,晚期的两边如果有不重要的一起砍掉,早期的砍掉
 function cutCancerCells(str){
   return str.replace(/c|[a-z]?C+[a-z]?/g,"")
 }遇见小写的c或者大C的左边是单个小写[a-z]右边是[a-z] 非贪婪匹配.
特殊情况:'dhcCo'
"dh" 当删除c后下标会转移到C 开始从C匹配 忽略掉左[a-z]
6,给一个字符串,删除左右两侧给定的字符.
 在原型上实现
 c既是这个给定的字符
 String.prototype.trim=function(c){//默认空格替换不了全角 
  var re=/^c*|c*$/gi//构造一个正则表达式 开头以这个c开头和c结尾的  
  if(c===undefined){//如果这个C没有传参写死 \s任意空白符
    re = /^\s*|\s*$/gi//处理空白 以及全角空格
  }else{//传了就构造
   c=c.replace(/(?=[^\w\s])/g,'\\')//如果这个c是一个符号,转义
   var re=new RegExp('^'+c+'*|'+c+'*$','gi')
  }
  return this.replace(re,'')//替换这个字符串 
}
去空格 面试必备
function trim(str) {
return str.replace(/^\s+|\s+$/g, '');
}
function trim (str) {
return str.replace(/^\s*(.*?)\s*$/g, "$1");
}//这里使用了惰性匹配 *?,不然也会匹配最后一个空格之前的所有空格的
将每个单词的首字母变成大写 
function titleize (str) {
  return str.toLowerCase().replace(/(?:^|\s)\w/g, function (c) {
  return c.toUpperCase();
  });
  }
转驼峰
  function camelize (str) {
    return str.replace(/[-_\s]+(.)?/g, function (match, c) {
    return c ? c.toUpperCase() : '';
    });
    }
    console.log( camelize('-moz-transform') );
    // => "MozTransform"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值