正则表达式

孤街醉人 提交于 2020-01-10 20:20:32

基础

正则表达式的创建

JavaScript有两种方式创建一个正则表达式:

var reg=/a/g;
var reg=newRegExp("a","g");

正则中分为两个部分 一个是正则匹配内容 另一个是修饰符部分

修饰符分为 i不区分大小写 g全局从头查找到尾部 m匹配多行

正则表达式的属性和方法

// 属性
var reg=/a/g;
console.log(reg.flags) // 修饰符
console.log(reg.source) // 正则匹配的内容
// 方法
var reg=/a/g;
var str = "abcdefg"
reg.test(str); // true 判断字符串是否满足正则匹配内容
reg.exec(); // 查找字符串中满足正则匹配内容的结果 并且返回一个数组 这个数组只有一个元素
            // 几个属性
            // groups 群组
            // index 查找到的索引下标
            // input 当前查找的字符串是什么
            // 没用的方法哦

正则表达式在字符串方法中的应用

str.search()

按照正则表达式查找字符串中的内容 返回优先查找到的第一个元素下标

var str="abcdefg";
console.log(str.search(/a/));  // 0 第一个

str.split();

按照正则表达式匹配内容 切割字符串 并且返回一个数组

var str="abcdefg";
console.log(str.split(/[cf]/g)) // 用c或f进行切割

str.replace()

按照正则表达式匹配内容 进行替换 可以替换成相同的 也可以替换成不同的

// 使用方法
str.replace(正则表达式,回调函数(item,index){
    // return返回要替换的内容
})

// 第一题
var str = "abcdeabcde"
str=str.replace(/a/g,function(item,index){
    return index===0?"x":"y";
})
console.log(str) // xbcdeybcde 第一个a换成x 剩下的a换成y

// 第二题
var str = "abcdeabcde"
var arr=[];
str.replace(/a/g,function(item,index){
    arr.push(index)
})
console.log(arr) // 0,5 查找所有匹配正则元素的下标

// 第三题
var str = "abcdefghigkl"
str=str.replace(/[bdf]/g,"0") 
console.log(str) // a0c0e0ghigkl 将满足正则的替换成0

// 第四题
var str="abcabcabf";
str = str.replace(/[abc]/g,function(item){
    switch(item){
        case "a" : return "1"
        case "b" : return "2"
        case "c" : return "3"
    }
})
console.log(str) // 12312312f a替换为1 b替换为2 c替换为3

str.match()

在这里 可以传入一个正则表达式

如果该正则表达式:

1.不是全局g查找 那么这个方法与exec()相同

2.不是全局查找 但是加群组 则先返回找到的元素外 再返回群组元素

3.是全局查找 将会返回满足正则的所有元素的数组

元字符

.

. 可以代表任意 单个 字符

console.log("cetcotcat".match(/c.t/g)) // 匹配c什么t
console.log("cetc.tcat".match(/c\.t/g)) // 匹配c.t  需要使用转义字符\
console.log("caaatcbbbbt".match(/c...t/g)) // 匹配caaat

[ ]

可以满足方括号内的任意一个字符

console.log("cetcotcat".match(/c[ae]t/g)) // cat cet

// [1-31] 相当于 [1-3 1] 匹配1 2 3
// [a-Z] 报错
// [A-z] 其中字母以外的其他字符 不能用
// [a-zA-Z] 大小写字母
// a[b.c]b 方括号[]中的. 是字符.    abb a.b acb 
// a[\[\]]]b 方括号[]中的[] 需要转义
// [aaaaa] 方括号[]中的重复是无意义的

中括号中的 ^

[ ]第一位 使用^ 表示除了^后面的字符外都满足

console.log("abcafcadcaec".match(/a[^f]/c/g)) // abc adc aec 不要中间是f的 
console.log("abcafcadcaec".match(/a[a^f]/c/g)) // 如果不在第一位 就表示字符^

转义特殊字符

\w [a-zA-Z0-9]
\W [^a-zA-Z0-9]
\d [^a-zA-Z0-9]
\D [^a-zA-Z0-9]
\s 空格
\S 非空格

// 剔除空格
var str="    ac  bg  de   ";
str=str.replace(/\s/g,"");
console.log(str) // acbgde 将所有的空格替换为空字符串""

{ }

一般情况下

{}内的数字 代表需要匹配几次

var str="1978-12-19"
var reg = /\d{4}-\d{2}-\d{2}/
console.log(reg.test(str)) // true {}内写一个数 代表固定重复几次

reg1 = /abc{2}/ // 这里是abcc
reg2 = /(abc){2}/ // 这里是abcabc
reg3 = /a{0}/ // 没有a 意味着匹配一个空字符

{1,} 需要满足一次及一次以上
{0,} 需要0次或者0次以上
{3,8} 需要满足3至8次

? + *

? 代表匹配前面的表达式满足0次或1次 {0,1}
+ 代表匹配前面的子表达式一次或多次 {1,}
- 代表匹配前面的子表达式零次或多次 {0,}

// 我想要 str 里的 item和items
var str = "item and items and itemes"
var arr=str.match(/items?\s/g).map(function(item){ 
        // "item "或者"items " ?代表有没有s都行 这时三个都可以通过 但是后面还需要有\s空格才可以匹配 所以只有前两个 但是末尾有空格
    return item.replace(/\s/g,""); // 将空格替换为空字符串
})
console.log(arr);

贪婪匹配 非贪婪匹配

在默认的情况下为贪婪匹配 重复会从大向小查找

var str = "aaaaaabbb"
console.log(str.match(/a{2,4}/g)) // "aaaa" "aa" 并不是"aa" "aa" "aa"

console.log("aaaaaa".match(/a.{3,4}/g)) // aaaa
console.log("aaaaaabbb".match(/a{0,4}/g)) // aaaa aa "" "" "" ""
console.log("bbbabbbaaabbbbaabbb".match(/a{1,}/g)) // a aaa a 
console.log("bbbabbbaaabbbbaabbb".match(/a{0,}/g)) // 算上空字符 17个

加个问号 就是非贪婪匹配了

var str = "aaaaaabbb"
console.log(str.match(/a{2,4}?/g)) // "aa" "aa" "aa"
.+? .*?
// 我想要a开始b结束 中间有零个或多个字符的字符串
// .是任意字符 *是0次或多次
var str = abaab;
console.log(str.match(a.*b)) // abaab 贪婪模式中 尽可能大的截取 不符合预期
console.log(str.match(a.*?b)) // ab aab 非贪婪模式 越短越好 满足就截取

// 同理 .+? 有一个或多个字符
var str = ababaab
console.log(str.match(a.+?b)) // abab aab   ab中间必须有1或多个字符 不能截出ab这种

// 将下列所有标签都换成p标签
var str = "<div>def<span>ghi</span></div><div><a href='#'>abc</div>"
var str = str.replace(/<\/?.+?>/g,function(item){ //< 开始 /可有可无 .+? 一个以上的字符 >结束 
    console.log(item)
    if(item.match(/\//)) return "</p>"
    else return "<p>"
})
console.log(str)

|

或者 指明两项之间的一个选择

如果是a或者b 可以直接用[ab] 但如果是ab或者bc 只能使用ab|bc

// 如果|得一端没有内容,则认为匹配空字符
console.log("abcdef".match(/|a|b/g)) // "" "" "" "" "" "" ""
console.log("abcdef".match(/a||b/g)) // a "" "" "" "" "" ""
console.log("abcdef".match(/a|b|/g)) // a b "" "" "" "" ""

^$

起始和结束

// 判断输入的数字是1-31之内的
<body>
    <input type="text"><span></span>
    <script>
        var input, span;
        init();
        function init() {
            input = document.querySelector("input");
            span = document.querySelector("span");
            input.addEventListener("input", inputHandler);
        }
        
        function inputHandler(e) { 
            if (this.ids) return; // 如果定时器存在 跳出
            this.ids = setTimeout(function (input) {
                clearTimeout(input.ids); // 清除定时器
                input.ids = false; 
                testInputValue(input.value);
            }, 500, this); // 0.5秒进入一次testInputValue
        }

        function testInputValue(txt) {
            console.log(txt.match(/^[1-9]$|^[12][0-9]$|^3[01]$/))
            // 从开始到结束1-9 或者10-29 或者30-31
            if (/^[1-9]$|^[12][0-9]$|^3[01]$/.test(txt)) { // 通过了 
                span.textContent = "输入正确";
                span.style.color = "green";
            } else { // 没通过
                span.textContent = "输入错误";
                span.style.color = "red";
            }
        }
    </script>
</body>

( )

群组

var str="13811111111".match(/(\d{3})(\d{4})(\d{4})/).slice(1).reduce(function(value,item,index){ // match在没有全局g且有群组的情况下 会先返回符合的元素 再返回群组
    return index===1 ? value+"****" : value+item;
},"")
console.log(str);

// $1就是第一个群组,$2就是第二个群组,$3就是第三个群组
var str="13822222222".replace(/(\d{3})(\d{4})(\d{4})/,"$1****$3");
console.log(str);

断言

// 零宽正向先行断言 (?=a)
// 找出后面紧跟"d"的位置 替换为"D" 
console.log("abcdabcd".replace(/(?=d)/g,"D")); // abcDdabcDd
// 找出后面紧跟"b"的"a"的位置 替换为"A"
console.log("abaccb".replace(/a(?=b)/g,"A")); // Abaccb

// 零宽负向先行断言 (?!a)
// 找出后面没有紧跟"d"的位置 都替换为"D"
console.log("abcdabcd".replace(/(?!d)/g,"D")); // DaDbDcdDaDbDcdD c后面是d 不加
// 找出后面没有紧跟"b"的"a"的位置 替换为"A"
console.log("abaccb".replace(/a(?!b)/g,"A")); // abAccb

// 零宽正向后行断言 (?<=a)
// 找出前面是"d"的位置 替换为"D" 
console.log("abcdabcd".replace(/(?<=d)/g,"D")); // abcdDabcdD
// 找出前面是"b"的"a"的位置 替换为"A"
console.log("abaccb".replace(/(?<=b)a/g,"A")); // abAccb

// 零宽负向后行断言 (?<=a)
// 找出前面不是"d"的位置 替换为"D" 
console.log("abcdabcd".replace(/(?<!d)/g,"D")); // DaDbDcDdaDbDcDd a前面是d 不加
// 找出前面不是"b"的"a"的位置 替换为"A"
console.log("abaccb".replace(/(?<!b)a/g,"A")); // Abaccb

案例

实现添加类名addClass和删除类名removeClass 且添加相同类名不会重复

<body>
    <div class="  div1       div3   div2 "></div>
    <script>
        function addClass(elem,className){
            // 将原来的class与需要添加的class连起来 取不是空格的地方
            // match加全局 没有群组 返回满足正则的所有元素的数组
            // 也就是去除空格后的所有类名
            var arr=(elem.className+" "+className).match(/\S+/g); 
            
            
            arr=arr.filter(function(item,index,arr){
                    // 去重 item在数组中的下一个位置开始 还有没有重复的
                    // 如果没有重复的 就放入数组
                    return arr.indexOf(item,index+1)<0;
            });
            elem.className=arr.join(" "); // 给elem添上classname
        }

        function removeClass(elem,className){
            var arr=elem.className.match(/\S+/g); // 把原来的className取出
            var arr1=className.match(/\S+/g); // 把删除的className取出
            arr1.forEach(function(item){ // 遍历需要删除的ClassName item是要删的
                arr=arr.filter(function(t){
                    return t!==item; // 返回arr中不等于item的类名
                });
            });
            elem.className=arr.join(" ");// 给elem添上classname
        }
    </script>
</body>

2[2[abc]3[bc]]

var str = "3[2[2[abc]3[d]]4[e]]";

function decodeString(str) {
    var reg1 = /\d+\[[a-zA-Z]+\]/g;
    // 数字 [  字母  ] 有全局没有群组 返回所有符合规则的元素
    // 只能匹配到中间没有字符的 所以从最内层的开始
    var reg2 = /(\d+)\[([a-zA-Z]+)\]/ 
    // (数字) [ (字母) ] 有群组没有全局 返回符合的元素和群组元素

    if (!reg1.test(str)) return str; // 出口
    str = str.replace(reg1, function (item, index) {
        console.log(item) // 最内层拆分的每一个组合
        var arr = item.match(reg2).slice(1); 
        // 通过match群组拿出数字和字符 第一项是符合的元素(自己) 所以截掉
        // arr中第一项是数字 第二项是字母
        var s = arr[1].repeat(arr[0]);
        return s; // s替换最内层的每个组合
    });
    str=decodeString(str) // 递归
    return str;
}

console.log(decodeString(str));
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!