通俗理解正则表达式

这不是入门级文章,但如果你对正则表达式有了解,或使用过,也许能帮助你快速回忆。阅读此文需要你之前使用过正则表达式或者有些了解,因为我没有写很多的例子。总结正则表达式,只是因为个人在几年的积累之后,想通俗简单的概述正则表达式是什么,能做什么。网上有很多关于正则表达式,但总感觉专业术语太多,读起来太拗口或绕弯子。最后两小节来自正则表达式30分钟入门教程,有部分修缮。

正则表达式字符串由两种基本字符组成:原义文本字符和元字符。所谓元字符就是正则表达式中具有特殊意义的专用字符。

元字符

一个元字符可能代表的是一个数字、字母、位置或数量。

代表字符


代码


说明


.


匹配除换行符以外的任意字符


\w


匹配字母或数字或下划线或汉字


\s


匹配任意的空白符


\d


匹配数字


\S


与\s相反


\D


与\d相反


\W


与\w相反

代表数量


代码


说明


*


重复零次或更多次


+


重复一次或更多次


?


重复零次或一次


{n}


重复n次


{n,}


重复n次或更多次


{n,m}


重复n到m次

代表位置


代码


说明


\b


匹配单词的开始或结束


\B


不是单词开头或结束的开始


^


匹配字符串的开始


$


匹配字符串的结束

转义字符

既然元字符在正则表达式中有特殊意义,如果现在要把它们当成一般原义文本字符,怎么办?在元字符前添加反斜杠\,表示当前元字符已经失去了正则表达式中的特殊意义,变成了一个原义文本字符。

预定义字符集

代表字符的元字符范围太广,如果只是想匹配某小范围内的字符,该怎么办?

很简单,使用方括号列出来即可。如[aeiou]或[.?!],表示只能从出现方括号中出现的字符。

需要注意的是:在这个方括号中,前面的所有元字符都不再是元字符,只有一个是元字符,就是连字符-。

  • 如果连字符在两个字符之间,那么就表示范围,连字符本身不算,如[0-9], [a-z]等;
  • 如果连字符后面没有字符,则表示连字符也是预定义的字符集的字符之一,如[*%-];

在预定义字符集中,可以使用转义字符

反义(antonymy)

有时只需要查找不属于某个简单定义的字符集的字符,这就是反义


代码


说明


\W


匹配任意不是字母,数字,下划线,汉字的字符


\S


匹配任意不是空白符的字符


\D


匹配任意非数字的字符


\B


匹配不是单词开头或结束的位置


[^x]


匹配除了x以外的任意字符


[^aeiou]


匹配除了aeiou这几个字母以外的任意字符

或 | 分支

这相当于或语句,具体方法是用垂直线|把不同的规则分隔开。如0\d{2}-\d{8}|0\d{3}-\d{7}这个表达式能匹配两种以连字号分隔的电话号码:一种是三位区号,8位本地号(如010-12345678),一种是4位区号,7位本地号(0376-2233445)。

分组(group)

所谓分组,其实就是把小括号()中正则表达式作为一个小的匹配单元。

分组的作用有两个:

  • 默认情况下,正则表达式会解析器给每一个小组分配一个组号,通过这种方式,后面的正则表达式就可以通过组号引用这个小组匹配的内容
  • 小组后可以跟代表数量的元字符,简化正则表达式书写;比如,(\d{1,3}\.){3}\d{1,3}是一个简单的IP地址匹配表达式。

小组后跟代表数量的元字符有一个问题需要注意:感觉应该是生成了若干个小组,但其实就是一个分组,因为组号是解析器解析的时候给的,代表小组的字符串在整个正则表达式字符串中只出现了一次,所以只分配了一个唯一的组号。因此,正则表达式执行完后,这个组匹配的内容是最后一次匹配的内容。

比如:

/(\d{1,3}\.){3}\d{1,3}/g.exec("201.202.203.204");

结果:["201.202.203.204", "203."]

后面的正则表达式通过组号引用前面分组匹配的内容,这个就叫后向引用。组号的规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,依此类推。引用的时候记得在组号前加上斜杠。

比如:

/\b(\w+)\b\s+\1\b/.test("hellohello");  // true

/\b(\w+)\b\s+\1\b/.test("hellohell");  // false

分组的语法:


代码/语法


说明


(exp)


匹配exp,并捕获文本到自动命名的组里


(?<name>exp)


匹配exp,并捕获文本到名称为name的组里,也可以写成(?‘name‘exp)


(?:exp)


匹配exp,不捕获匹配的文本,也不给此分组分配组号

零宽断言

零宽断言像\b、^、$一样用于指定一个位置,但这个位置应该满足一定的条件,这个条件就是断言。因为这个断言不会像分组一样有组号,不消耗匹配的字符串,所以称之为零宽断言。


代码/语法


说明


(?=exp)


断言这个位置的后面,一定有匹配exp的内容;


(?<=exp)


断言这个位置的前面,一定有匹配exp的内容;


(?!exp)


断言这个位置的后面,一定没有匹配exp的内容


(?<!exp)


断言这个位置的前面,一定没有匹配exp的内容

注释

注释用(?#comment)表示。

贪婪与懒惰(greedy and idle)

一段固定的正则表达式,它所能匹配的可能是整个字符串,也可能只是整个字符串的一部分。假如出现一段正则表达式既能匹配整个字符串,也能只匹配部分该如何处理?

/h.*o/.exec("hello ho");  // ["hello ho"]

/h.*?o/.exec("helloho");  // ["hello"]

以上这个例子中,匹配hello使用的是懒惰匹配,而没有问号限定的则是使用的贪婪匹配。

所谓贪婪匹配就是尽可能多的重复,以匹配尽可能多的字符。反之,懒惰匹配就是匹配尽可能少的字符。默认是贪婪算法,只有在表示数量的元字符后使用了懒惰限定符(也就是问号)才表示这个地方使用懒惰算法。


懒惰限定符


语法


说明


*?


重复任意次,但尽可能少重复


+?


重复1次或更多次,但尽可能少重复


??


重复0次或1次,但尽可能少重复


{n,m}?


重复n到m次,但尽可能少重复


{n,}?


重复n次以上,但尽可能少重复

平衡组(balance group)/递归匹配(recursive match)

前面讲的所有匹配都是线性的,对于匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,则上面的一切方法都没用。因为你不可能知道括号什么时候出现,而且如果左括号和右括号出现的次数不相等怎么办?如何匹配到最长的,配对的括号之间的内容?

这里需要用到以下的语法构造:

  • (?‘group‘exp) 把捕获的内容命名为group,并压入堆栈(Stack)
  • (?‘-group‘exp) 从堆栈上弹出最后压入堆栈的名为group的捕获内容,如果堆栈本来为空,则本分组的匹配失败
  • (?(group)yes|no) 如果堆栈上存在以名为group的捕获内容的话,继续匹配yes部分的表达式,否则继续匹配no部分
  • (?!) 零宽负向先行断言,由于没有exp,试图匹配总是失败

为了避免(和\(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把xx <aa <bbb> <bbb> aa> yy这样的字符串里,最长的配对的尖括号内的内容捕获出来?

<                         #最外层的左括号

[^<>]*                #最外层的左括号后面的不是括号的内容

(

(

(?‘Open‘<)    #碰到了左括号,在黑板上写一个"Open"

[^<>]*       #匹配左括号后面的不是括号的内容

)+

(

(?‘-Open‘>)   #碰到了右括号,擦掉一个"Open"

[^<>]*        #匹配右括号后面不是括号的内容

)+

)*

(?(Open)(?!))         #在遇到最外层的右括号前面,判断黑板上还有没有没擦掉的"Open";如果还有,则匹配失败

>                        #最外层的右括号

更多


常用转义字符及其他部分元字符


代码/语法


说明


\a


报警字符(打印它的效果是电脑嘀一声)


\b


通常是单词分界位置,但如果在字符类里使用代表退格


\t


制表符,Tab


\r


回车


\v


竖向制表符


\f


换页符


\n


换行符


\e


Escape


\0nn


ASCII代码中八进制代码为nn的字符


\xnn


ASCII代码中十六进制代码为nn的字符


\unnnn


Unicode代码中十六进制代码为nnnn的字符


\cN


ASCII控制字符。比如\cC代表Ctrl+C


\A


字符串开头(类似^,但不受处理多行选项的影响)


\Z


字符串结尾或行尾(不受处理多行选项的影响)


\z


字符串结尾(类似$,但不受处理多行选项的影响)


\G


当前搜索的开头


\p{name}


Unicode中命名为name的字符类,例如\p{IsGreek}

时间: 2024-11-03 05:34:35

通俗理解正则表达式的相关文章

通俗理解数据库隔离机制

=========================================== 原文链接: 通俗理解数据库隔离机制   转载请注明出处! =========================================== 在理解数据库隔离机制的时候发现网上很多文章都是千篇一律,解释语言太过于标准书面化,描述的晦涩难懂,因果关系模糊.在这里将自己对隔离机制的理解描述一下,力争做到能够通过浅显的语言描述出来. 数据库隔离机制是对于多线程同时操作数据库而言的.对于单线程操作数据库不存在所谓

分布式理论之一:Paxos算法的通俗理解

维基的简介:Paxos算法是莱斯利·兰伯特(Leslie Lamport,就是 LaTeX 中的"La",此人现在在微软研究院)于1990年提出的一种基于消息传递且具有高度容错特性的一致性算法. Paxos算法目前在Google的Chubby.MegaStore.Spanner等系统中得到了应用,Hadoop中的ZooKeeper也使用了Paxos算法,在上面的各个系统中,使用的算法与Lamport提出的原始Paxos并不完全一样,这个以后再慢慢分析.本博文的目的是,如何让一个小白在半

Activity生命周期的通俗理解

一般一个Activity有三种状态: 1.在屏幕上是可见的且可操作的,他是活跃或运行状态,负责响应用户操作. 2.失去焦点但仍然可见时,他处于暂停状态.也就是说未被完全遮蔽,所以该Activity仍对用户可见,但是当系统处于繁忙的时候下,有肯会杀死该Activity. 3.完全被另一个Activity覆盖时处于停止状态.也有可能被杀死. Activity生命周期中各方法的调用情况 1.onCreate(Bundle savedStatus):第一次创建时调用,只调用一次. 2.onStart()

SSL服务器认证过程通俗理解!

理解有错误的地方,请高手指正! 1,CA中心,有一套自己的公钥和私钥,服务器用自己的私钥去生成一个自认证的证书 2,CA中心的自认证证书是有公信力的,一般被客户端所熟知,发放到每个客户端! 3,客户端需要将CA中的自认证证书加入信任列表! 4,服务器要加入CA体系,要向CA中心申请,CA中心验证了服务器的资料后,向server发放一个证书(key),里面包含了一个秘钥 5,CA发给server的证书是用CA自己的秘钥和申请者的秘钥(key)加密过的, 6,证书里面包含:申请者的身份信息.申请者公

深入理解正则表达式环视的概念与用法

在<深入理解正则表达式高级教程-环视>中已经对环视做了简单的介绍,但是,可能还有一些读者比较迷惑,今天特意以专题的形式,深入探讨一下正则表达式的环视的概念与用法. 深入理解正则表达式环视的概念与用法 一.环视的概念 (一)环视概念与匹配过程示例 示例一:简单环视匹配过程 (二)什么是消耗正则的匹配字符? 示例二:一次匹配消耗匹配字符匹配过程 示例三:多次匹配消耗匹配字符匹配过程 二.环视的类型 (一)肯定和否定 (二)顺序和逆序 · 两种类型名称组合 · 四种组合的用法 四种组合正则与环视的摆

关于面对对对象之接口的通俗理解

一些人写代码,按照计算机思考的那个模式写,写出来的代码,能实现功能,但是拓展性不好,而有些人写代码,是按照人看世界的那些思路去写,写出来的代码 看起来像那么回事儿,而且也非常的符合逻辑,这是为什么?为什么同样是写代码,为什么写出来的东西会完全不一样了? 最近一直在反思自己写的代码,以前写,都是为了完成某项功能而写,写完了也就完事儿了,可是最近却不是这样了,最近想打问题是,写代码是不是只要在实现功能的层面上就可以了了?后来得出的答案是,代码其实还可以写的更加的灵活多变一点的 那么今天我们就来谈谈关

网络七层协议的通俗理解

OSI七层模式简单通俗理解 这个模型学了好多次,总是记不住.今天又看了一遍,发现用历史推演的角度去看问题会更有逻辑,更好记.本文不一定严谨,可能有错漏,主要是抛砖引玉,帮助记性不好的人.总体来说,OSI模型是从底层往上层发展出来的. 这个模型推出的最开始,是是因为美国人有两台机器之间进行通信的需求. 需求1: 科学家要解决的第一个问题是,两个硬件之间怎么通信.具体就是一台发些比特流,然后另一台能收到. 于是,科学家发明了物理层: 主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介

矢量控制的通俗理解

关于矢量控制,通俗理解是: 1. 先把电机想像成2块飞速旋转磁铁,定子磁铁和转子磁铁.进一步可以引申为定子磁场和转子磁场. 2. 电机的电磁转矩与定子磁场强度.转子磁场强度.2块磁铁之间的夹角的正弦成正比.关于这一点不难理解,两块磁铁对齐的时候(0度,sin0=0;),不存在电磁转矩:两块磁铁相差90度的时候(sin90=1;),电磁转矩达到顶峰:  3. 接下来控制的目标就是: 1)稳定其中的一个旋转磁场的强度(恒定磁场):  2) 控制磁铁之间角度为90度(磁场定向FOC): 3) 控制另一

通俗理解TCP握手次数是三次

理解之后,应该说是至少三次就可以保证可靠传输了. 看到网上一篇帖子http://www.cnblogs.com/TechZi/archive/2011/10/18/2216751.html是这么说的,“我Google该问题答案后发现,网络上对于“三次握手”的过程都有很详细的描述,但对于为什么需要“三次握手”来建立连接却没有很好的答案.只能求助于书本了.”后面有谢希德树和另一本书的解释,其实还是太书面化,不够通俗,但是看到后面引到google论坛看到一个让我非常满意的答案. https://gro