从 例子 开始 入门 正则 表达式(-)

4,272 阅读4分钟

正则入门

  正则 是个难啃的骨头,以前看着会正则的人 感觉都好牛逼。于是工作了2年了终于鼓起勇气啃这个骨头了。。

例子入手

  首先我们先看下相关的字符代表。我们先看这个例子。这个🌰就是验证字符串是否是数字。

let regex = /^[0-9]+$/;
let number = '123';
let string = 'abc';
regex.test(number); // true
regex.test(string); // false

可能很多人这时用到了百度谷歌一下然后复制过去直接用就OK了,但是这样沉淀不到东西,所以我们来静下心看看这个正则到底什么意思,首先我们要了解的是相关的

  • ^ :脱字符,匹配开头,在多行匹配中匹配行开头,有时也表示求反的概念。
  • $ :美元符号, 匹配结尾,在多行匹配中匹配行结尾。
  • {m,} 表示至少出现m次。
  • {m} 等价于{m,m},表示出现m次。
  • +: 等价于{1,},表示出现至少一次。记忆方式:加号是追加的意思,得先有一个,然后才考虑追加。
  • *:等价于{0,},表示出现任意次,有可能不出现。记忆方式:看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来。

可能这时你有些不理解 [0-9],其实他等价于 [0123456789] ,在正则里可以缩写所以为 [0-9], 同理[a-z],[A-Z]也是同样的道理。为什么使用正则因为他书写简单,我们还可以简化,让我们等下看看接下来的这些字符,思考下怎么继续简化。

那我们大概能猜到这个意思代表什么了,从 开头(^) 到 结尾($) 0-9([0-9]) 出现 至少一次 (+) , 所以就很好理解了,为什么这个是验证数字的想必就能理解了。
接下来我们再来看一些特殊字符:

  • \d就是[0-9]。表示是一位数字。记忆方式:其英文是digit(数字)。
  • \D就是[^0-9]。表示除数字外的任意字符。
  • \w就是[0-9a-zA-Z_]。表示数字、大小写字母和下划线。记忆方式:w是word的简写,也称单词字符。
  • \W是[^0-9a-zA-Z_]。非单词字符。
  • \s是[ \t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页符。记忆方式:s是space character的首字母。
  • \S是[^ \t\v\n\r\f]。 非空白符。
  • .就是[^\n\r\u2028\u2029]。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符除外。记忆方式:想想省略号...中的每个点,都可以理解成占位符,表示任何类似的东西。

  好的我们看到了 \d 其实就是 [0-9],此时忽然恍然大悟,原来上面的正则还能简化:

let regex = /^\d+$/; // /^[0-9]+$/;

这时我们大概 已经懂得这个正则代表什么东西了,之后再出现验证用户输入的是不是数字,就别再百度了,分分钟就写出来。

举一反三

  我们已经了解之前的这个例子后,大概能推敲如何实现验证全是字母:

let regex = /^[a-z]+$/;
let string = 'abc';
let number = '123';
regex.test(number); //false
regex.test(string);//true

正则是区分大小写字母的,所以,我们要验证大写字母的时大概是这样:

let regex = /^[A-Z]+$/;
let string = 'abc';
let STRING = 'ABC'
let number = '123';
regex.test(number); //false
regex.test(string);//false
regex.test(STRING); //true

好了我们已经反二了,接下来我们来反三,即是大写字母又是小写字母,怎么去写?

let regex = /^[a-zA-Z]+$/

估计到这里我们都已经算入门了,不是很复杂的正则都可以自己去写了。

考验

接下来我们来看一些常用需求:

正则 验证 手机 。

手机号码是几位,emmmm,等下我先数数 183 XXX XXX XX ,噗,11位,好吧当我没说。那我们分析下,手机号, 首先全部都是数字, 开头第一位一定是 数字 1 ,然后只要满足 11位就可以了,我们已经把需求整理清楚了,如果我们用 js 去写会怎么写?我这里随意写一写,可能有更好的方式

const isPhone = (number) => {
    const len = number.length;
    if (typeof number !== 'string' || len !== 11  || number[0] !== '1') {
        return false;
    }

    for (let i = 0; i < len; i++) {
        if (isNaN(number[i])) return false;
    }

    return true;
}

console.log(IsPhone('18367490590')); //true


可见一个 js 书写是多么麻烦,也可能是我的解决方式不是很牛逼,随便写写,各位有什么好的解决方案也可以给我评论。。扯远了。现在我们来看看要是用正则怎么写?

let regex  = /^1\d{10}$/;

一行代码搞定。就是这么简单,让我们分析一下。

  • ^ 开头匹配
  • 1 开头没毛病
  • \d 表示 [0-9] 代表必须是数字
  • {10} 也是 {10, 10} 表示 [0-9]出现10次,加上1 也就是说 11位。
  • $ 结尾匹配没毛病。 以上一行代码就搞定了。很简便其实分析下也不是很难。

正则 验证 邮箱 。

我就不写什么 js 的版本了,有兴趣的同学可以自己尝试写写。我们看看邮箱的正则应该是有这么几个需求的:

  • xxx@xxx.xxx
  • @ 前需要有任意字符
  • 邮箱 有 @ 符号。
  • @后有任意字符
  • 要有 .
  • . 后跟任意字符
let regex = /^\w+@\w+\.\w+/;

简单分析一下:

  • \w我们知道是[0-9a-zA-Z_]下划线
  • + 代表至少出现一次 好比 {1,}
  • @ 必须需要。
  • . 这里要注意下,因为 . 是特殊正则字符, 代表通配符, 我们这里需要的是 "." 字符串,所以加了 \ 进行转译

补充案例

  之前的例子们大概动了一些东西,让我们再来看几个例子。

匹配16进制颜色值

大概是这样:

#ffbbad #Fc01DF #FFF #ffE

写法:

let regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;

分析:
开头是#号,表示一个16进制字符,可以用字符组[0-9a-fA-F]。然后 {6} 代表 出现6 次,这时候你可能有点迷 这个代表什么 稍等引出这个 | 是分支的概念。再说说后面其实也很好理解 字符组[0-9a-fA-F] 出现3次。

  • | 分支,其实可以理解为这个是编程中的或,很容易理解了。那么,我们知道或者是惰性的,一个成立不向下执行,这里其实也一样。

让我们再来一个案例:

验证 匹配 yyyy-mm-dd : 2018-10-20

正则如下:

var regex = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;

分析一波:

  • 年 \d{4} [0-9]出现4次。
  • 月 共12个月, 十位0的话就是 [1-9]月,十位1的话就是 [0-2]个月。
  • 日 最多31天 ,十位0的话就是 [1-9]天,十位1,十位2就是[0-9] 3的话只有0或者1。

结语。

正则是个大工程这里只是一些简单的正则,比如还有惰性匹配等 我们还没有见到, 在后面的系列中我会慢慢的加入进去。未完...