【JavaScript从入门到精通】第二十九课 JS中的正则表达式

此内容来自开课吧石川微信公众号

在学习正则表达式之前,我们先来复习一下JS里操作字符串的方法:

  • search 查找
  • substring 获取子字符串
  • charAt 获取某个字符
  • split 分割字符串,获得数组

现在我们想办法找出一个字符串里的所有数字,如果我们采用JS操作字符串的方法:

var str='12 fff 87 er334 233 -=-=fa80';
var arr=[];var tmp='';
for(var i=0;i<str.length;i++)
{
    if(str.charAt(i)>='0' && str.charAt(i)<='9')
    {
        tmp+=str.charAt(i);
    }
    else
    {
        if(tmp)
        {
            arr.push(tmp);
            tmp='';
        }
    }
}
if(tmp)
{
    arr.push(tmp);
    tmp='';
}
alert(arr);

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

这样虽然实现了效果但非常麻烦。如果用正则表达式,做法如下:

var str='12 fff 87 er334 233 -=-=fa80';
alert(str.match(/d+/g));

效果与上一个程序相同。可以看到使用正则表达式可以大幅度简化代码的复杂度,这也是我们学习正则表达式的最主要理由。

正则表达式基础

首先我们来探讨一下什么是正则表达式。

所谓的正则,表达的是一种规则或者模式,用于规范字符串。举一个最简单的例子,对于一个邮箱来说,它的必须遵循的格式为:一串英文or数字or下划线 @ 一串英文or数字.一串英文。这一套规则计算机并不能直接读懂,如果我们希望使用计算机来校验邮箱,那么就需要用到正则表达式将这个规则以计算机能够理解的方式告诉它。

普遍来说,我们给正则表达式的定义为:一种强大的字符串匹配工具。不过对于正常人来说,正则表达式是很难以读懂的。

现在我们来编写我们的第一个正则表达式。在JS正则同样是以对象的形式存在,其对象名为RegExp,它有一个参数为具体规则,这个规则就是用来对字符串进行匹配的。

var re=new RegExp('a');
var str='abcdef';
alert(str.search(re));

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

在这段代码里,‘a’就是一个最简单的正则表达式,它代表的含义就是a本身,因此通过search方法返回的值为0。对于正则表达式来说,它还有另一种写法:

var re=/a/;

效果与上面相同。我们将上面的写法称为JS风格,而下面的写法称为perl风格。

由于JS不区分大小写,所以我们前面的正则表达式是无法寻找到A的。现在,如果我希望能同时寻找到A和a,正则表达式应该怎么写呢?在正则里,还为我们提供了一个选项参数。

var re=new RegExp('a','i');
var str='Abcdef';
alert(str.search(re));

i(ignore)就是忽略大小写后再进行比较的选项。对于perl风格我们采取这种写法也是可行的:

var re=/a/i;

对于上述例子来说,使用正则和不使用正则差距其实并不是很大,现在我们来举一个有很大必要使用正则的例子:现在我们有这么一串字符串:“adsf 23 23 vcxzxcv”,我们希望找出它出现的第一个数字。我们用字符串的方法可以完成这个目标,但要知道,我们并不清楚第一个数字是多少,0-9都有可能,那么使用search方法我们就需要分别实验,总共查询10次才能完成。而在正则表达式里,有一种转义的写法:d,它代表的含义就是所有数字。

var str='adsf 23 23 vcxzxcv';
var re=/d/;
alert(str.search(re));

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

这样就可以很轻易的找到第一个数字。

我们前面寻找字符用的都是search方法,但search方法只能寻找到字符出现的位置,而另一种match方法可以将所有匹配的内容全部提取出来。例如,

var str='asdf 34 656 cvs3';var re=/d/;alert(str.match(re));

结果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

可以看到它只为我们提取出了第一个数字3,为了获取所有数字我们需要用到另一个选项“g”:

var str='asdf 34 656 cvs3';
var re=/d/g;
alert(str.match(re));

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

g(global)的含义代表找到全部符合条件的字符,一般叫它全局匹配。但可以看到,它为我们自动进行了切片(因为我们每次只要求了一个数字),我们希望输出的数字在字符串内如果是连续的,输出时也是连续的,应该怎么办呢?

这里我们要用到正则里面的一个新概念:量词。量词描述了正则表达式里一类字符出现的次数。这里我们使用+量词,它代表的含义是一个或一个以上。使用量词我们就可以达成目的了:

var str='asdf 34 656 cvs3';
var re=/d+/g;
alert(str.match(re));

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

这里我们再讲另一个字符串方法与正则表达式的配合使用:replace方法。replace方法用于字符串内字符的替换,第一个参数为需要替换的字符,第二个参数为使用什么字符替换。现在我们有一个字符串“abc aaa erw”,如果我们想把里面的a全部替换为数字0,使用replace方法完成:

var str='abc aaa erw';
alert(str.replace('a','0'));

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

可以看到的是,replace方法只能替换字符串内第一个符合要求的字符。实际上,replace方法如果不搭配正则表达式使用,其功能是非常有限的。现在我们使用正则表达式来讲代码改写:

var str='abc aaa erw';
var re=/a/g;
alert(str.replace(re,'0'));

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

这样就可以替换所有的a了。利用这种方法,我们就可以做一个简单的铭感词过滤程序了。

正则的基础组成部分

我们前面已经研究了正则表达式在JS里的基础用法,下面我们来看看正则表达式的基础组成部分。

-[]:一般称为元字符。它有好几种用法。-[abc]:这种用法代表或的意思,即abc任一个。例如正则表达式[abc]pc,那么apc,bpc,cpc都符合正则表达式的要求。-[a-z] 和 [0-9]:上面这种写法的简化版,代表a-z中的任意一个和0-9中的任意一个字符。-[^a-z]:^的含义为排除。因此这种写法的意思是:除去a-z中的任意一个字符。

这几个写法可以进行组合,例如[^a-z0-9]代表除去小写英文字母和数字之外的任意一个字符。

这里我们举一个小说的例子。我们从网页上采集到的小说文本携带着html标签,现在我们希望通过正则表达式将这些标签去掉。

window.onload=function ()
{
    var oTxt1=document.getElementById('txt1');
    var oTxt2=document.getElementById('txt2');
    var oBtn=document.getElementById('btn1');

    oBtn.onclick=function ()
    {
        var re=/<[^<>]+>/g;
        oTxt2.value=oTxt1.value.replace(re, '');
    };
};

为了避免正则表达式将整个小说的字符全部过滤掉,我们将<>排除在匹配字符外。

此外,在正则表达式里,我们有这几种转义字符:

  • .(点),代表任意字符
  • d,w,s,分别代表数字,英文+数字+下划线,空白字符
  • D,W,S,上面三种转义字符的对立事件

量词

我们之前已经解释过什么是量词,那么在正则表达式里量词还以哪些形式存在呢?

  • {n}:正好出现n次。例如,d{8},代表连续8位的任意数字
  • {n,m}:最少出现n次,最多出现m次。例如QQ号,有5位到11位,且第一位不能为0,则其正则表达式为:[1-9]/d{4,10}
  • {n,}:最少n次,最多不限。实际上+量词就相当于{1,}。还有?量词的含义为{0,1},也就是最少出现零次,最多出现1次;量词的含义为{1,},表示可以出现任意多次也可以不出现

现在我们来写一个电话号码的正则表达式。电话号码的结构为:以0开头的区号,一共为3位或4位-非0开头的具体号码,共8位-分机号,可以为1-5位。其中区号和分机号是可以不写。结果如下:(0d{2,3}-)?[1,9]d{7}(-d{1,5})?。

常用正则例子

正则表达式通常用于校验,这里我们来尝试写一个邮箱校验的例子。在写这个例子之前,我们还有一些新的知识要讲。我们刚才已经分析过了邮箱的具体结构:一串英文or数字or下划线 @ 一串英文or数字.一串英文。经过分析

<html>
    <head>
        <meta charset="utf-8">
        <title>
            无标题文档
        </title>
        <script type="text/javascript">
        window.onload=function ()
        {
        var oTxt=document.getElementById('txt1');
        var oBtn=document.getElementById('btn1');
        oBtn.onclick=function ()
        {
        var re=/w+@[a-z0-9]+.[a-z]+/i;
        if(re.test(oTxt.value))
        {
            alert('合法的邮箱');
        }
        else
        {
            alert('你丫写错了');
        }
        };
        };
        </script>
    </head>
    <body>
        <form>
            <input type="text" id="txt1"> <input type="button" value="校验" id="btn1">
        </form>
    </body>
</html>

效果如下:

【JavaScript从入门到精通】第二十九课 JS中的正则表达式

这样就可以对邮箱进行鉴别了。正则表达式采用test的方法进行正则与字符串的校验,但test方法存在一定的问题:只要字符串的一部分符合正则要求,它就会认为整个字符串都符合要求并会返回true。

例如我在这里输入邮箱的时候,在邮箱前面添加汉字,我们会发现它依然能通过娇颜。为了避免这种情况出现,我们需要用到^字符。我们知道,^字符出现在[]内时,它代表的含义是排除,但当它出现在[]外时,代表的是行首,也就是字符串的开头;,对应的,我们用$代表一个字符串的行尾。我们将表达式“w+@[a-z0-9]+.[a-z]+”修改为 “^w+@[a-z0-9]+.[a-z]+$”,代表一个字符串从开头到结尾只能出现我们正则表达式的内容,这样就可以避免问题了。

如需转载,烦请注明出处:https://www.qdskill.com/javascript/4442.html

发表评论

登录后才能评论