5分钟系列:正则表达式,需要掌握的二三事。

313 阅读5分钟

这是我的千日蜕变计划第一篇,我计划在未来的1000天,三天更新一篇博客。希望大家监督,也希望自己可以坚持。

建议阅读时间:5分钟

写作时长:70分钟

内容:正则基础

这算是我阅读《正则表达式必知必会》的笔记整理和总结。主要分为四个部分,主要如下:

  1. 基本语法
  2. 边界符
  3. 子表达式和表达式嵌套
  4. 回溯引用

基本语法

  • 纯文本: /abc/ 将匹配 abc

纯文本没什么好说的,只是匹配纯文本,需要注意的是,默认匹配第一个。

  • . : .点在正则中表示任意一个字符
  • \ : \ 在正则中,永远出现在一个有着特殊含义的字符序列的开头。
  • []: []中括号在正则中,匹配其中的某一项
    • 比如: [AaBbCc] 将 匹配AaBbCc中的任意一项,记住,是任意一项。
  • ^ : ^ 这个不知道怎么读的符号, 要注意的是,它是正则中为数不多的两种意思的特殊符号。
    • 如果^[] 中,代表取反的意思。比如[^1-9]代表匹配1-9以外的任意字符。
    • 如果^ 不在 [] 中,则代表以^后面的字符开头方可匹配。比如/^.jpg$/代表以任意字符开头的字符串。
  • $ : 上面说到以字符串开头,那么$ 就是以字符串结尾特殊字符了。
  • 空白符 :常见的空白符有以下几种
    • \r 回车
    • \n 换行
    • \t 制表符
    • \s 任意空白符

除了以上简单的使用以外,正则还有一些方便使用的字符,如下:

  • \d : 代表 [0-9], 匹配任意一个0-9的字符。你可以这样记忆: 一只小狗(d),对着0-9的数字进行算术运算。
    • \D : 反之,代表匹配[0-9]以外的任意字符。后面还会有大写代表相反的意思,我将会以大写同上来表示。
  • \w : 代表 [a-zA-Z0-9_]。这些字符,通常会在密码中用到,你可以这样记忆: 博物馆有一个皇冠(w), 你非常想拿出来看看,可惜,玻璃被密码[a-zA-Z0-9_]锁着了,你无法打开。
    • \W: 大写同上,代表相反

ok, 以上多说,都是匹配单个字符,我想匹配多个怎么办?下面这些特殊字符,是时候表现真正的技术了。

  • + : 匹配一个或者多个:记忆: 既然是+号,那就已经+上了,最起码也是1个对吧,即表示1个或者n个。
  • * : * 星号其实不必多说,0个或者多个。
  • ? : 注意?也是为数不多的两种意思的特殊字符。
    • 表示0个或者1个。记忆: 你用一个鱼钩?钓鱼,永远只会钓到1个或者0个。
    • ?第二个意思是代表懒惰匹配,我将在下面贪婪匹配部分展开说明。

以上匹配的都不够精确,如果要精确匹配怎么拌?

  • {} : {} 花括号代表精确匹配
    • {3}: 精确匹配3个
    • {2, 4}: 区间匹配, 2-4个之间
    • {3, } : 至少匹配,至少匹配3次
  • 在正则中,+* 都是贪婪匹配。举个🌰:

aa<div>test1</div>bb<div>test2</div>cc

如果想匹配上<div>test1</div>,你可能或这样写:<div>.*</div>

你得到的结果将会是这样的: <div>test1</div>bb<div>test2</div>

因为 * 是贪婪的,它将会一直匹配下去,知道最后一个为止。

如果要正确匹配的话,应该是这样: <div>.*?</div>, 问号?在这里代表懒惰匹配。

一般来说,需要用到懒惰匹配的如下

 {m,n}?
 {m,}?
 ??
 *?
 +? 

记忆: 麦当劳m的门n旁边,有一个懒惰的厨子,做了一个夹心+*蛋糕, 这个蛋糕形似一个问号?

边界匹配

有些时候,并不想匹配字符,而是想匹配一个单词。只是想单纯的匹配 a hello b , 而 不想匹配到 ahellob 中间的hello 怎么办呢? 这时候,\b 就派上用场了。

  • \b : 单词的开头或者结尾。
    • 上面的案例,需要这样匹配。\bhello\b.
    • 需要注意的是,\b只匹配一个位置,不匹配任何字符. 也就意味着, \bhello\b 匹配的是5个字符,而非7个。
  • \B : 非单词的开头或者结尾。
    • 这个怎么理解?举个例子: hello-worldhello - world
    • \B-\B来匹配的话,将会匹配到第二个 -.

子表达式和嵌套

有的时候,重复的表达式写很多次是很烦的,比如:

&nbsp;&nbsp;&nbsp;&nbsp; 将会匹配 4 次,也要写4遍

() : ()小括号代表分组,也叫子表达式。上面的案例,也可以这样写:(&nbsp;){4}.如果没有分组,你这样写的话:&nbsp;{4} 将会匹配&nbsp;;;;.

有的时候,子表达式里面也要嵌套子表达式。比如,你想匹配一个ip

ip的规则是这样: 由3个点连接,4个小于255的数字组成, 比如255.255.255.255

这时候的正则需要这样来写,将会使用到子表达式的嵌套。

(((\d{1,2})|(1|\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1|\d{2})|(2[0-4]\d)|(25[0-5]))

回溯引用

()子表达式的另外一个用途就是回溯引用,所谓回溯引用就是前后一致匹配。比如说:

<Hh>([1-6]).*?</[Hh]([1-6])> 这将匹配 <h1></h1><h2></h2>.

看似很完美,看看下面这个,是不是也会匹配呢?

<h1> Abc </h3>

当然会匹配。可是这不是我们想要的结果不是么?

回溯引用将会解决这个问题:

<Hh>([1-6]).*?</[Hh]\1>, 这里的\1, 将会匹配第一个子表达式。简单来说,前面的子表达式是啥,我就匹配啥。


好了,到这里,就差不多了。

我是海明月,前端小学生。

我的千日蜕变计划正式启动,如果您觉得写(总结)得还行,希望您能够监督我执行。谢谢。

如果有不对的地方,也希望大佬指正。