第n次学习后我终于对正则明白了一点点

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jplyue/article/details/78624772

Reference 正则表达式30分钟入门教程

废话:
第一次看这篇经典入门,还没到一半就放弃了。这次终于看到了三分之二才放弃!虽然每次学习之后感觉自己都没有懂,但是这次终于惊喜地发现在没有懂的过程中,懂了一点点。因为正则,真的是前端路上迈不过去的一道深深的坎啊!每次写代码都要悔恨为什么不懂正则!为什么!

这篇文章是对30分钟入门教程的个人理解,如果您已读懂该教程,请忽略这篇文章

1. 正则到底是什么鬼

使用命令行操作、或者数据库操作,你肯定使用过 * 这个操作符,我们经常用它来匹配全部,正则就像是对这个操作符的延伸。比如说我在使用git提交文件,我一般会git add *, 但是如果我不想添加全部,想要添加以select开头的文件呢,这个逻辑就可以用正则来表示。 (这只是一个假想,不要当真)

2. 最简单的正则表达式

/hi/  #用来匹配hi

正则表达式在分析字符串的时候,通常会把字符串拆分成一个一个的单词,并且连单词的缝隙也不放过,这点稍后解释。

所以/hi/ = h + i ,这个正则就是用来匹配字符串中包含h,后面紧跟着一个i的字符串,你可以在浏览器里测试

/hi/.test('hi')  # true
/hi/.test('hhhhiiii') # true
/hi/gi.test('hhhHIiii') # true

gi表示一种匹配模式,使用g则进行全局的匹配,使用i会忽略大小写

\b 单词的缝隙

如果你想要精确匹配hi这个单词,在hhhiiiii这种应该返回false,要如何做呢?

/\bhi\b/.test('hi')

想象每个英文单词的缝隙都隐藏着一个\b

welcome to beijing
\bwelcome\b     \bto\b   \bbeijing\b

虽然说单词之间是由空格、逗号之类的分隔符隔开的,但是呢,空格也是一个字符,它属于字符串的一部分,\b却是一个隐形字符,可以帮助你悄无声息地判断出一个是否是一个完整单词,而不用消耗你的字符串元素。大家叫他元字符,metacharacter

. 点(除了换行符以外的任意字符)

.也是一个元字符。

Q: 匹配hi后面不远处跟着一个Lucy

-> 翻译:hi + 中间有很多不明的字 + Lucy

\bhi\b.*\blucy\b

一个.只能匹配一个字符,多个点就用.*来表示。

* 也是一个元字符,但是它表示的是数量,.*可以理解为,点这个模式被乘以了n次,这个n是多少呢?

  1. *表示任意数,毕竟*是个通配符嘛
  2. +表示 >= 1
  3. {6} 就是精确的6次
  4. {6, 12} 6~12次之间
  5. {6, } >=6次
  6. ?出现1次或不出现

所以你可以这样使用

.*
.+
.{6}
.{6,12}
.{6,}

.可以替换成其他的元字符,可能你常常看到他们:

  • \d 表示一位数字0, 1, 2,…9

    举例: 0\d{2}-\d{8}, 意思就是,这个字符串以0开头,然后跟着一个2个数字,跟着连字符-,跟着8位数字

  • \s 任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等

  • \w 匹配字母或数字或下划线或汉字等
  • [afe] 如果你想要匹配自己定义的一个集合,可以使用[ ],表示a或f或e中的一个字符,注意这也是一个单字符匹配,或者符号集[.?!]。同时也可以指定一个范围[a-z] [A-Z] [0-9], 此时的[0-9]等同于\d, [a-zA-Z0-9_]等同于\w
表示字符 表示数量
. *
\d ?
\s +
\w {n},{n,m},{n,}
[aeiou]

反义

大写是小写的反义

字符 含义
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符
<a[^>]+> 匹配<a开始,非>结束的内容,其实是<a..任意内容..>

^ $

^ 表示字符串的开始,$表示字符串的结束。开始时^的取反功能和开始标志让我有点捉摸不清。不过/^asjfhkajsdfhjkshf\$/这两个元素通常就被安置在开始和结束的位置,如果你不明所以,只要在开头看到^,或者在结尾看到$,只要明白这是开始和结束即可。

为什么要加这两个标志呢,因为匹配可能发生在中部尾部头部,所以如果你想要从头到尾去规定一个字符串就要加上这个限制条件,比如你规定一个长度只能为6的字符串,你就需要加上头尾,否则它匹配一个8个长度的字符串,中间确实有6个字符,也会返回true

举例:

/.{6}/.test('123456789'); #true
/^.{6}$/.test('123456789'); # false 

字符转义

匹配. * \ 这些特殊字符,加上\进行转义:., *, \

例子分析

\(?0\d{2}[) -]?\d{8}

( 转义,?一个括号出现1次或不出现,然后跟着0,然后2个数字,然后)或者-,)-出现一次或0次,然后8个数字

解析的时候要把 字符和字符的数量 放在一起考量。

(0nn)12345678
0nn-12345678
0nn12345678

分枝条件 -

分枝就像路分成了两条,但哪个都能到达目的。类似于 || ,

 注意顺序,原因是匹配分枝条件时,将会从左到右地测试每个条件,如果满足了某个分枝的话,就不会去再管其它的条件了。其实和js的 ||一样呢

\d{5}|\d{5}-\d{4} 与 \d{5}-\d{4}|\d{5} 结果不同

分组

用小括号圈起来成为一个子表达式。唯一一个不用看就理解的信息

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

分析:
23n或252或0nn或0n. 重复3次,23n或252或0nn
最后一个没有点,所以单独拎出来,重复三次的小组,规定了一个合规的ip数字,后面跟着点。

后向引用(? )

\b(\w+)\b\s+\1\b
解释:匹配重复的单词。\b(\w+)\b 表示一个单词,s+许多空格,\1表示\b(\w+)\b匹配的单词,它会被自动捕获到\1中。分组匹配时,匹配的结果会按顺序储存在\2 \3 \4..
\b(?<Word>\w+)\b\s+\k<Word>\b

如果你觉得\1实在太不友好,此处的<Word>就是你重命名\1的方式。<Word>指代,\k<Word>表示反向引用。(在js测试时这个语句报错,不明白==)
分类 代码/语法 说明
捕获 (exp) 匹配exp,并捕获文本到自动命名的组里
(?exp) 匹配exp,并捕获文本到名称为name的组里,也可以写成(?’name’exp)
(?:exp) 匹配exp,不捕获匹配的文本,也不给此分组分配组号
零宽断言 (?=exp) 匹配exp前面的位置
(?<=exp) 匹配exp后面的位置
(?!exp) 匹配后面跟的不是exp的位置
(? 匹配前面不是exp的位置
注释 (?#comment) 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

Q: 捕获是什么意思?
https://www.cnblogs.com/yakun/p/3795589.html

猜你喜欢

转载自blog.csdn.net/jplyue/article/details/78624772