JS_正则表达式

day10-正则表达式

用于匹配字符串中字符组合的模式,主要用来验证客户端的输入数据。

用户填写完表单单击按钮之后,表单就会被发送到服务器,在服务器端通常会用PHP、ASP.NET等服务器脚本对其进行进一步处理。因为客户端验证,可以节约大量的服务器端的系统资源,并且提供更好的用户体验。

  • 创建方式

    • 1.字面量创建正则;

      var reg = /./;

    • 2.构造函数形式创建正则;

      var reg = new RegExp();

    区别:用字面量创建的正则,规则已经确定不会改变;如果规则存在改变的可能,那么必须使用构造函数创建正则表达式。

    修饰符 描述
    g 全局匹配
    i 大小写不敏感
    m 多行匹配
  • 删除字符串中的大小写a

    var str = "abcAbCAabc";
    str = str.replace(/a/gi,"");
    console.log(str);
    
  • 复制正则表达式

    var reg = /a/g;
    var reg1 = new RegExp(reg.source, reg.flags);
    console.log(reg === reg1);    //false
    
  • test()

    判断字符串中是否有符合正则规则的字符,返回 truefalse

    var reg = /a/;
    console.log(reg.test("bfAg"));    //false
    
  • exec();

    以数组的形式显示字符串中符合正则规则的字符,包括索引、下标和原字符;否则返回null

  • match

    字符串查找方法 => 按照规则查找并以数组形式返回查找结果;
    math匹配的数组:【1】是匹配到的元素,【2】是元素所在的下标,【3】捕获组数组 或 undefined(如果没有定义命名捕获组)。

    • 如果没有任何修饰符,效果与exec相同
    console.log(str.match(/a/g));
    
    var str = "吴彦祖张彦祖李彦祖刘彦祖";
    console.log(str.match(/吴彦祖/));        //匹配的是“吴彦祖”3个字
    console.log(str.match([/吴彦祖/]));  //匹配是的“吴”或者“彦”或者“祖”
    

    程序本性是懒惰的,只要匹配到任意一个满足条件的就会立即终止程序;

    • 如果使用群组,math可以区分群组
    var str = "ab12ca3d4eA2f4g";
    console.log(str.match(/(2)([a-z])/g)); //2c 2f 如果使用群组,match还可以区分群组
    
    • 查找字符串中的“c.t”
    var str = "cotdogc.tcat";
    console.log(str.match(/c\.t/g/)); //转义字符\.表示字符串".";\\表示\
    console.log(str.match(/c[.]t/));//把原字符放在中括号内会失效,[.]相当于字符"."       
    
    • 查找字符串中的cat和cot
    var str = "cotdogc.tcat";
    console.log(str.match(/c[oa]t/g));    //[]内代表任意一个字符
    console.log(str.match(/c[A-Z]t/g));   //任意大写字母A-Z之间的一个字符
    console.log(str.match(/c[a-Z]t/g));   //报错,a(97) > Z(90)
    console.log(str.match(/c[A-z]t/g));   //不会报错,但是包含了90-97之间的字符
    console.log(str.match(/[a-zA-Z]/)); //任意字母之间的一个字符
    console.log(str.match(/[a]/)); // [a]等同于a
    
    • 取反
    console.log(str.match(/[^0-9]/)); //除了字母
    console.log(str.match(/[a-z^abc]/));//如果[]里^不是第一位,这个则表示^字符
    console.log(str.match(/[^^]/)); //不要上箭头,等同于[^\^]
    
    • 贪婪匹配
    console.log("aaaaaaaaaa".match(/a{2,4}/g));   //["aaaa", "aaaa", "aa"]
    console.log("colour".match(/colou{0,1}/g));   //["colou"]
    console.log("aaaaaa bb aabb".match(/a{0,4}/g)); 
    //["aaaa", "aa", "", "", "", "", "aa", "", "", ""]
      //第二个bb前面的第一个空格,第二个bb中间的一个空格,第二个bb后面一个空格
    console.log("abaabaaaaaaa".match(/a{2,}/g));//无上限 ["aa", "aaaaaaa"]
    
  • search

    如果匹配成功,则 search() 返回正则表达式在字符串中首次匹配项的索引;否则,返回 -1

    注:仅能查找到第一个满足规则的字符下标,不能进行全局查找

    var pattern = /good/ig;
    var str = 'good good study!,day day up!';
    console.log(str.search(pattern)); //返回第一个匹配到的good索引的下标:0
    
  • replace

    替换匹配到的数据

    str.replace(regexp|substr, newSubStr|function)
    可以指定一个函数作为第二个参数;
    
    • 通过正则修饰符全局替换所有满足规则的字符
    var str = "ab12ca3d4eAfg";
    str = str.replace(/[df]/gi,"z"); // 将字母替换为字母z
    console.log(str); //ab12ca3z4eAzg
    
    • 第二个参数,可以是函数
    var num = 0;
    var str = "abcdefg"
    str = str.replace(/[a-z]/gi,function(item,index){
      return ++num;    
    })
    console.log(str); //1234567
    
    image.png
    var pattern = /Good/ig;
    var str = 'good good study!,day day up!';
    console.log(str.replace(pattern, 'hard'));//hard hard study!,day day up!
    
    var str = "hello world";
    //replace每次替换的都是函数的返回值
    var res = str.replace(/o/g, function(){       //将o换成一个或者两个**
        console.log(1);
        return Math.random() > 0.5 ? "*" : "**";
    })
    
  • 字符匹配

    \s 空白字符 \S 除了空白字符
    \d 数字[0-9] [0-9] \D 非数字[^0-9] =>65535-10 = 65525个 [^0-9]
    \w 字母数字下划线 [0-9a-zA-Z] \W 除了字母数字下划线 [^0-9a-zA-Z]
    . 任意字符[^\n\r] .* 任意个任意字符
    .+ 一个以上任意字符

    注意:[.]代表匹配一个"." ; 而没有元字符的".",代表匹配任意字符

    var str = ["卢本伟", "张本伟", "a本伟", "b本伟", "!本伟", "\n本伟", "\r本伟", "本伟", "赵梦玥", "天佑", "李本伟", "马飞飞", "PGONE", "乔碧萝"].join(",");
    
    var reg1 = /.本伟/g;    //除了\n和\r之外,任意字符开头的本伟
    var reg2 = /[^\n\r]本伟/g
    
    // [\s\S] 真正的全部字符 , 会匹配到回车符和换行符;
    var reg3 = /[\s\S]本伟/g;
    
    console.log(str.match(reg1));
    // ["卢本伟", "张本伟", "a本伟", "b本伟", "!本伟", ",本伟", "李本伟"]
    console.log(str.match(reg2));
    // ["卢本伟", "张本伟", "a本伟", "b本伟", "!本伟", ",本伟", "李本伟"]
    console.log(str.match(reg3));
    //  ["卢本伟", "张本伟", "a本伟", "b本伟", "!本伟", "↵本伟", "本伟", ",本伟", "李本伟"]
    
  • 匹配次数问题

    符号 匹配次数
    * 表示任意次 0 或多次
    表示匹配1次或0次
    + 表示至少1次
    {m,n} 表示m次到n次
    {m,} 表示至少m次
    *? 表示非贪婪匹配(匹配到符合内容的字符串时,会尽快地结束匹配)
    当该字符紧跟在任何一个其他限制符(,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪*的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
  • 非贪婪匹配

    一般用在左边或者右边有内容 ,并且使用了*+这种可以匹配任意多个内容,可以利用非贪婪匹配查找某个内容之间最少的结果。

    var str = "3[abc]2[cde]5[ce]";
    var str = str.match(/\d+\[[a-zA-Z]+\]/g).reduce(function(value, item) {
        var arr = item.match(/(\d+)\[([a-zA-Z]+?)\]/).slice(1);
        return value + arr[1].repeat(Number(arr[0]));
    }, "");
    console.log(str);//abcabcabccdecdececececece
    
    var str = "5[abc]2[cde]";
    str = str.match(/\d+\[[a-zA-Z+?]\]/g).reduce(function(value,item){
        item.match(/\d+\[([a-zA-Z]+?)\]/);//加()表示群组,让它在数组中独立地显示出来
    },"");
    console.log(str);
    
  • 起始和结束

    ^代表起始,$代表结束

    console.log("concat".match(/^c.t$/g));    //null
    
  • 预查

    • 肯定预查——紧随其后

    ?= n 匹配任何一个其后紧跟n的字符串

    console.log("abacad".replace(/a(?=c)/g,"z"));//abzcad
    
    • 否定预查

    ? ! n 匹配任何其后没有紧接指定字符串 n 的字符串。

    console.log("abacad".replace(/a(?!c)/g,"z"));//zbaczd
    
    • 反向预查
    console.log("abacaddc".replace(/(?<=a)c/g,"z"));//abazaddc
    
    • 反向否定预查
    console.log("abacaddc".replace(/(?<!a)c/g,"z"));//abacaddz
    
  • {}中代表重复的次数

    console.log("abcaabcaaabc".match(/a{3}/g));   //aaa
    console.log("abcaabcaaabc".match(/a{0}/g));   
    //打印长度为13的数组,每一项为空字符,{0}代表""字符
    console.log("abaabaaaaa".match(/a{0,}/g))//["a", "", "aa", "", "aaaaa", ""]
    
  • 两个||,中间匹配的是空字符串

    console.log("abcdef".match(/a||b/g));
    //错误的,后面的b永远也匹配不到["a", "", "", "", "", "", ""]
    
  • 匹配第一个双引号中的内容

    console.log('hac"hack"abc"www"ppp'.match(/\"[^\"]*\"/)); //"hack"
    
  • 取出句子中的指定内容

    var str = "中国有四大名著,分别是<西游记>、<水浒传>、<红楼梦>、<三国演义>。";
    var att = str.match(/\<[^\<\>]+\>/g).map(function(item){
        return item.slice(1,-1);
    });
    console.log(att); //["西游记", "水浒传", "红楼梦", "三国演义"]
    
  • [1-31]代表什么含义?

    代表1,2,3;不是1至31

    /^[1-9]$|^[12][0-9]$|^3[01]$/.test(input.value)
    
  • 验证手机号

    var phoneReg = /^1[3-9]\d{9}$/;
    var phoneReg1 = /^(13[0-9]|14[3579]|15[0-3,5-9]|16[6]|17[0135678]|18[0-9]|19[89])\d{8}$/;
    phoneReg.test(phoneValue);
    
  • 验证当前页面是否为html结尾

    var htmlReg = /.*\.html$/
    console.log(htmlReg.test(location.href));
    
  • 验证邮箱

     var reg = /^[0-9a-zA-Z_.-]{4,20}+[@]+[0-9a-zA-Z_.-]+([.][a-zA-Z]+){1,2}$/;
    
  • 验证姓名

    var name = /^[\u4e00-\u9fa5]{2,6}$/;
    
  • 验证年月日

    <input type="text"><span></span>
    
    init();
    
    function init() {
        var input = document.querySelector("input");
        var span = document.querySelector("span");
        input.span = span;
        input.addEventListener("input", inputHandler);
    }
    
    function inputHandler(e) {
        if (this.ids) return;
        this.ids = setTimeout(function(input) {
            clearInterval(input.ids);
            input.ids = 0;
            getRightText(input);
        }, 500, this)
    }
    
    function getRightText(input) {
    
        if (/^[12]\d{3}\-(0[1-9]|[0-2])\-(0[1-9]|[12][0-9]|3[01])$/.test(input.value)) {
            input.span.textContent = "正确";
            input.span.style.color = "green";
        } else {
            input.span.textContent = "错误";
            input.span.style.color = "red";
        }
    }
    
  • 拼接className,并且去重

    <div class="div0 div1  div2"></div>
    
    var div = document.querySelector("div");
    addClassName1(div," div4   div5 div3");
    

    trim() 去除字符串的头尾空格:

    • 方法一

      function addClassName1(elem,className){
          var arr = elem.className.trim().split(/\s+/);
          var arr1 = className.trim().split(/\s+/);
          arr.forEach(function(item){
              if(arr.indexOf(item) < 0) arr.push(item);
          });
          elem.className = arr.join(" ");
      }
      
    • 方法二

      function addClassName2(elem,className){
           var arr1 = className.trim().split(/\s+/);
          elem.className = elem.className.trim().split(/\s+/).reduce(function(value,item){
              return arr1.indexOf(item) > -1 ? value : value.concat(item);
          },[]).concat(arr1).join(" ");
      }
      
    • 方法三

      function allClassName3(elem,className){
         var arr1 = className.trim().split(/\s+/);
          elem.className = elem.className.trim().split(/\s+/).filter(function(item){
              return arr1.indexOf(item) < 0; //把没找到的返回
          }).concat(arr1).join(" ");
      }
      
  • removeClassName

    
    //把没有的返回出去,拼接上
    function removeClassName(elem,className){
        var arr1 = className.trim().split(/\s+/);
        elem.className = elem.className.trim().split(/\s+/).filter(function(item){
            return arr1.indexOf(item) < 0; //把没找到的返回
        }).join(" ");
    }
    
  • 将手机号中间4位变为*

    var tel = "18812345678";
    console.log(tel.replace(/^(\d{3})(\d{4})(\d{4})$/,"$1****$3"));
    
  • 实现trim()方法

  1. 方法一

这里的*表示匹配0个或者多个,此时我们需要考虑两种情况:一个是前面存在空格,另一个是后面存在空格。所以我们使用|来进行匹配。

var trim = str => str.replace(/(^\s*)|(\s*$)/g, "");
var str = "  abc d e fgh   ";
console.log(trim(str));
  1. 方法二

这里replace中的第二个参数$1,对应正则表达式中的(.*?)部分,匹配字符串中,除了前后空格之外的任意字符

function trim(str){
  let reg = /^\s*(.*?)\s*$/g;
  return str.replace(reg, "$1");
}
var str = "  abc d e fgh   ";
console.log(trim(str));
  1. 方法三

利用match方法,取匹配值的第二项参数(.*?),原理同上;

function trim(str) {
   str = str || "";
   if (str.length <= 0) return str;
   str = str.match(/(^\s*)(.*?)(\s*)$/);
   //match非全局匹配中的第【0】项是本身,第【1】项对应(^\s*)
   //第【2】项对应(.*?]),第【3】项对应(\s*)
   return (str && str[2]) ?? '';
}
var str = "  abc d e fgh   ";
console.log(trim(str))
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容