正则表达式常用语法

正则表达式

在编写处理字符串的程序或网页时,经常会有查找符合某些复杂规则的字符串的需要。 正则表达式 就是用于描述这些规则的工具。换句话说,正则表达式就是记录文本规则的代码。

概念

正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"),是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。

字符 是计算机软件处理文字时最基本的单位,可能是字母,数字,标点符号,空格,换行符,汉字等等。 字符串 是0个或更多个字符的序列。 文本 也就是文字,字符串。说某个字符串 匹配 某个正则表达式,通常是指这个字符串里有一部分(或几部分分别)能满足表达式给出的条件。

常用语法

  1. \b: 匹配一个单词边界,即字与空格间的位置。并不匹配单词分隔字符中的字符

在一篇英语文章中查找hi,如果直接使用hi查找,会查找出history、him、historical、hight等等,所以如果我们需要精确查找,可以使用 “\bhi\b”

  1. “.”:匹配除了换行符以外的任意字符,匹配的是字符

待匹配文本:history
正则表达式:.
匹配结果:
h
i
s
t
o
r
y

ps:换行符就是’\n’,ASCII编码为10(十六进制0x0A)的字符

  1. *:同样是元字符,不过它代表的不是字符,也不是位置,而是数量—它指定 *前边的内容可以连续重复出现任意次以使整个正则表达式得到匹配。通常与.一起用,". *"意味着任意数量的不包含换行的字符。

待匹配文本:history
正则表达式:.*
匹配结果:
history

  1. \d:匹配一位数字(0,或1,或2,或······)

待匹配文本:123456
正则表达式:\d
匹配结果:
1
2
3
4
5
6

如果同时使用其他元字符,我们就能构造出功能更强大的正则表达式。比如下面例子:

待匹配文本:012-12345678 012-87654321
正则表达式:0\d\d-\d\d\d\d\d\d\d\d
匹配结果:
012-12345678
012-87654321
ps:–不是元字符,只匹配它本身——连字符或减号

  1. {n,m}或{n}:连续重复匹配(≥n 和 ≤m次)或(n次)

上述例子中存在许多烦人的重复操作(\d\d\d\d\d),可以简化为:
待匹配文本:012-12345678 012-87654321
正则表达式:0\d{2}-\d{8}
匹配结果:
012-12345678
012-87654321

  1. \s:匹配 任意的空白符,包括空格,制表符(Tab),换行符,中文全角空格等
  2. \w:匹配字母或数字

匹配要求:匹配以字母a开头的单词
待匹配文本:apple align amazing
正则表达式:\ba\w*\b
匹配结果:
apple
align
amazing

  1. +:和上面的"*"类似,不同的是 * 可以匹配重复任意次(可能是0次—— ≥0),而+则匹配重复1次或更多次(≥1)

待匹配文本:123456 456789
正则表达式:\d+
匹配结果:
123456
456789

  1. ^:匹配你要用来查找的字符串的开头,这和\b类型,也是匹配一个位置
    $:匹配结尾,也是匹配一个位置

匹配要求:填写的内容必须是5位到12位数字
待匹配文本:123456789012
正则表达式:^\d{5,12}$
匹配结果:
123456789012
ps:因为使用了 ^$,所以输入的整个字符串都要用来和\d{5,12}来匹配,也就是说整个输入必须是5-12个数字

常用语法/元字符总结

代码说明
\b匹配单词的开始或结束
.匹配除换行符以外的任意字符
*重复零次或更多次
\d匹配数字
{n}重复n次
{n,}重复n到更多次
{n,m}重复n到m次
\s匹配任意的空白符
\w匹配字母或数字或下划线
+重复一次或更多次
^匹配字符串的开始
$匹配字符串的结束

字符转义

如果你想查找元字符本身的话,比如你查找 “.” ,或者 *,就出现了问题:你没办法指定它们,因为它们会被解释成别的意思。
这时你就得使用 \ 来取消这些字符的特殊意义。因此,你应该使用 \. 和 \* 。当然,要查找 \ 本身,你也得用 \\ .
例如: unibetter.com 匹配 unibetter.com , C:\Windows 匹配 C:\Windows 。

字符类

要想查找数字,字母或数字,空白是很简单的,因为已经有了对应这些字符集合的元字符,但是如果你想匹配没有预定义元字符的字符集合(比如元音字母a,e,i,o,u),可以使用 [aeiou] 即匹配任何一个英文元音字母,同理**[.?!]**匹配任何一个标点符号(.?!)

我们也可以轻松地指定一个字符范围,像 [0-9] 代表的含义与**\d**就是完全一致的:一位数字,同理[0-9a-zA-Z]也完全等同于\w

下面我将讲解一个更复杂的表达式:

待匹配文本:(010)12345678 022-12345678
正则表达式:(?0\d{2}[- )}?\d{8}
匹配结果:
(010)12345678
022-12345678

分析:
首先是一个转义字符 \(
它能出现0或1次(?)
然后就是一个0
后面跟着2个数字(\d{2})
然后是)或-或空格其中一个({- )})
它出现0或1次(?)
最后跟着8个数字(\d{8})

分支条件

上述更复杂的表达式可以匹配010)12345678或(023-09183092这样的”不正确“的格式。要解决这个问题,我们需要用到分支条件。
正则表达式中的 分支条件 指的是有几种规则,如果满足其中一种规则都应该当成匹配,具体方法是用|把不同的规则分隔开。
我将给出以下示例:

待匹配文本:010-12345678 0376-2233445
正则表达式:0\d{2}-\d{8}|0\d{3}-\d{7}
匹配结果:
010-12345678
0376-2233445
ps:该表达式能匹配以连字号分隔的电话号码:一种是三位区号,8位本地号,另一种是四位区号,7位本地号

待匹配文本:01212345678 (012)12345678
正则表达式:(0\d{2})[- ]?\d{8}|0\d{2}[- ]?\d{8}
匹配结果:
01212345678
(012)12345678
ps:该表达式能匹配3位区号的电话号码:其中区号可以用小括号括起来也可以不用,区号与本地号可以用连字号或空格间隔,也可以没有间隔。

分组

我们已经提到了怎么重复单个字符(直接在字符后面加上限定符就行了);但如果想要重复多个字符又该怎么办?你可以用小括号来指定 子表达式 (也叫做 分组 ),然后你就可以指定这个子表达式的重复次数了
下面我将给出一段匹配IP地址的正则表达式

待匹配文本:192.168.100.1 192.168.156.1
正则表达式:(\d{1,3}.){3}\d{1,3}
匹配结果:
192.168.100.1
192.168.156.1
ps:
要理解这个表达式,请按下列顺序分析:
\d{1,3} 匹配1到3位的数字
(\d{1,3}.){3} 匹配三位数字加上一个英文句号 这个整体 重复三次
最后加上一个一到三位的数字(\d{1,3})

上述表达式只能匹配ip格式的字符串,但无法匹配是否违规的IP,如256.300.888.999这种不可能存在的IP地址
所以改进如下:
((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)

反义

代码/语法说明
\W匹配任意不是字母、数字、下划线
\S匹配任意不是空白符的字符
\D匹配任意非数字的字符
\B匹配不是单词开头或结尾的位置
[^x]匹配除了x以外的字符
[^aeiou]匹配除了aeiou以外的字符

后向引用

使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个 组号 ,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。

匹配要求:匹配重复的单词
待匹配文本:went went go go height height
正则表达式:\b(\w+)\b\s+\1\b
匹配结果:
went went
go go
height height

ps:其他的也不多说了,其中的\1是分组1中捕获的内容(也就是前面匹配的那个单词)
例如前面匹配了went,整个表达式就相当于\bwent\b\s+went\b

你也可以自己指定子表达式的组名。请使用这样的语法:
(?<Word>\w+)(或者把尖括号换成 ’ 也行:(?‘Word’\w+))
这样就把\w+的组名指定为Word了,要反向引用这个分组捕获的内容,可以使用 \k<Word>

分类代码/语法说明
捕获(exp)匹配exp,并捕获文本到自动命名的组里
捕获(?<name>exp)匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name’exp)
捕获(?:exp)匹配exp,不捕获匹配的文本,也不给此分组分配编号
零宽断言(?=exp)匹配exp前面的位置
零宽断言(?<=exp)匹配exp后面的位置
零宽断言(?!exp)匹配后面跟的不是exp的位置
零宽断言(?<exp)匹配前面不是exp的位置
注释(?#comment)这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读

零宽断言

  1. (?=exp):也叫 零宽度正预测先行断言 ,它 断言自身出现的位置的后面能匹配表达式exp

待匹配文本:I am singing while you are dancing
正则表达式:\b\w+(?=ing\b)
匹配结果:
sing
danc

ps:匹配以ing结尾的单词的前面部分(除了ing以外的部分)

  1. (?<=exp):也叫 零宽度正回顾后发断言 ,它 断言自身出现的位置的前面能匹配表达式exp

待匹配文本:reading a book
正则表达式:(?<=\bre)\w+\b
匹配结果:
ading

ps:匹配 以re开头的单词的后半部分(除了re以外的部分)

  1. (?!exp):断言此位置的后面不能匹配表达式exp

待匹配文本:123b111a 1234
正则表达式:\d{3}(?!\d)
匹配结果:
123
111
234

ps:匹配 三位数字,而且这三位数字的后面不能是数字

  1. (?<!exp):断言此位置的前面不能匹配表达式exp

待匹配文本:
A2315461
B1234567
12345678202222
正则表达式:(?<![a-z])\d{7}
匹配结果:
123
111
234

ps:匹配前面不是小写字母的七位数字

  1. (?#comment):注释

使用示例:2[0-4]\d(?#200-249)|25[0-5](?#250-255)|[01]?\d\d?(?#0-199)

ps:匹配前面不是小写字母的七位数字

贪婪与懒惰

当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符

贪婪匹配

待匹配文本:aabab
正则表达式:a.*b
匹配结果:
aabab

ps:匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。

懒惰匹配

有时,我们更需要 懒惰 匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号 ?
即.*?意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复

待匹配文本:aabab
正则表达式:a.*?b
匹配结果:
aab
ab

懒惰限定符

代码/语法说明
*?重复任意次,但尽可能少重复
+?重复1次或更多次,但尽可能少重复
??重复0次或1次,但尽可能少重复
{n,m}?重复n到m次,但尽可能少重复
{n,}?重复n次以上,但尽可能少重复
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值