【正则表达式】

概述

正则表达式又称规则表达式。(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式通常被用来检索、替换那些符合某个模式(规则)的文本。正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。

简介

正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符"))操作的一种逻辑公式,就是用事先定义好的一些特定字符及这些特定字符的组合,组成一个"规则字符串",这个"规则字符串"用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

目的

播报编辑给定一个正则表达式和另一个字符串,我们可以达到如下的目的:1. 判断给定的字符串是否符合正则表达式的过滤逻辑(称作"匹配"):2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。

特点

正则表达式的特点是:

  1. 灵活性、逻辑性和功能性非常强;

  2. 可以迅速地用极简单的方式达到字符串的复杂控制。

  3. 对于刚接触的人来说,比较晦涩难懂。

由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容。

符号

正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面会给予解释。

在最简单的情况下,一个正则表达式看上去就是一个普通的查找串。例如,正则表达式"testing"中没有包含任何元字符,它可以匹配"testing"和"testing123"等字符串,但是不能匹配"Testing"。要想真正的用好正则表达式,正确的理解元字符是最重要的事情。

下表列出了所有的元字符和对它们的一个简短的描述。

|---------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 元字符 | 描述 |
| \ | 将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如,"\\n"匹配\n。"\n"匹配换行符。序列"\\"匹配"\"而"\("则匹配"("。即相当于多种编程语言中都有的"转义字符"的概念。 |
| ^ | 匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配"\n"或"\r"之后的位置。 |
| | 匹配输入行尾。如果设置了RegExp对象的Multiline属性,也匹配"\n"或"\r"之前的位置。 |
| * | 匹配前面的子表达式任意次。例如,zo*能匹配"z",也能匹配"zo"以及"zoo"。*等价于{0,}。 |
| + | 匹配前面的子表达式一次或多次(大于等于1次)。例如,"zo+"能匹配"zo"以及"zoo",但不能匹配"z"。+等价于{1,}。 |
| ? | 匹配前面的子表达式零次或一次。例如,"do(es)?"可以匹配"do"或"does"。?等价于{0,1}。 |
| {n} | n是一个非负整数。匹配确定的n次。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。 |
| {n,} | n是一个非负整数。至少匹配n次。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。 |
| {n,m} | m和n均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,"o{1,3}"将匹配"fooooood"中的前三个o为一组,后三个o为一组。"o{0,1}"等价于"o?"。请注意在逗号和两个数之间不能有空格。 |
| ? | 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串"oooo","o+"将尽可能多地匹配"o",得到结果"oooo",而"o+?"将尽可能少地匹配"o",得到结果 'o', 'o', 'o', 'o' |
| .点 | 匹配除"\n"和"\r"之外的任何单个字符。要匹配包括"\n"和"\r"在内的任何字符,请使用像"\\s\\S"的模式。 |
| (pattern) | 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用0...9属性。要匹配圆括号字符,请使用"\("或"\)"。 |
| (?:pattern) | 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符"(|)"来组合一个模式的各个部分时很有用。例如"industr(?:y|ies)"就是一个比"industry|industries"更简略的表达式。 |
| (?=pattern) | 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,"Windows(?=95|98|NT|2000)"能匹配"Windows2000"中的"Windows",但不能匹配"Windows3.1"中的"Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。 |
| (?!pattern) | 非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如"Windows(?!95|98|NT|2000)"能匹配"Windows3.1"中的"Windows",但不能匹配"Windows2000"中的"Windows"。 |
| (?<=pattern) | 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,"(?<=95|98|NT|2000)Windows"能匹配"2000Windows"中的"Windows",但不能匹配"3.1Windows"中的"Windows"。 |
| (?<=pattern) | *python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等 |
| (?<!pattern) | 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如"(?<!95|98|NT|2000)Windows"能匹配"3.1Windows"中的"Windows",但不能匹配"2000Windows"中的"Windows"。 |
| (?<!pattern) | *python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等 |
| x|y | 匹配x或y。例如,"z|food"能匹配"z"或"food"(此处请谨慎)。"z\|food"则匹配"zood"或"food"。 |
| xyz | 字符集合。匹配所包含的任意一个字符。例如,"abc"可以匹配"plain"中的"a"。 |
| \^xyz | 负值字符集合。匹配未包含的任意字符。例如,"\^abc"可以匹配"plain"中的"plin"任一字符。 |
| a-z | 字符范围。匹配指定范围内的任意字符。例如,"a-z"可以匹配"a"到"z"范围内的任意小写字母字符。 |
| a-z | 注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身. |
| \^a-z | 负值字符范围。匹配任何不在指定范围内的任意字符。例如,"\^a-z"可以匹配任何不在"a"到"z"范围内的任意字符。 |
| \b | 匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的"匹配"有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,"er\b"可以匹配"never"中的"er",但不能匹配"verb"中的"er";"\b1_"可以匹配"1_23"中的"1_",但不能匹配"21_3"中的"1_"。 |
| \B | 匹配非单词边界。"er\B"能匹配"verb"中的"er",但不能匹配"never"中的"er"。 |
| \cx | 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的"c"字符。 |
| \d | 匹配一个数字字符。等价于0-9。grep 要加上-P,perl正则支持 |
| \D | 匹配一个非数字字符。等价于\^0-9。grep要加上-P,perl正则支持 |
| \f | 匹配一个换页符。等价于\x0c和\cL。 |
| \n | 匹配一个换行符。等价于\x0a和\cJ。 |
| \r | 匹配一个回车符。等价于\x0d和\cM。 |
| \s | 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于 \\f\\n\\r\\t\\v。 |
| \S | 匹配任何可见字符。等价于\^ \\f\\n\\r\\t\\v。 |
| \t | 匹配一个制表符。等价于\x09和\cI。 |
| \v | 匹配一个垂直制表符。等价于\x0b和\cK。 |
| \w | 匹配包括下划线的任何单词字符。类似但不等价于"A-Za-z0-9_",这里的"单词"字符使用Unicode字符集。 |
| \W | 匹配任何非单词字符。等价于"\^A-Za-z0-9_"。 |
| \xn | 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,"\x41"匹配"A"。"\x041"则等价于"\x04&1"。正则表达式中可以使用ASCII编码。 |
| \num | 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,"(.)\1"匹配两个连续的相同字符。 |
| \n | 标识一个八进制转义值或一个向后引用。如果\n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n为一个八进制转义值。 |
| \nm | 标识一个八进制转义值或一个向后引用。如果\nm之前至少有nm个获得子表达式,则nm为向后引用。如果\nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若n和m均为八进制数字(0-7),则\nm将匹配八进制转义值nm。 |
| \nml | 如果n为八进制数字(0-7),且m和l均为八进制数字(0-7),则匹配八进制转义值nml。 |
| \un | 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(&copy;)。 |
| \p{P} | 小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀。中括号内的"P"表示Unicode 字符集七个字符属性之一:标点字符。 |
| \p{P} | 其他六个属性: |
| \p{P} | L:字母; |
| \p{P} | M:标记符号(一般不会单独出现); |
| \p{P} | Z:分隔符(比如空格、换行等); |
| \p{P} | S:符号(比如数学符号、货币符号等); |
| \p{P} | N:数字(比如阿拉伯数字、罗马数字等); |
| \p{P} | C:其他字符。 |
| \p{P} | *注:此语法部分语言不支持,例:javascript。 |
| \< | 匹配词(word)的开始(\<)和结束(\>)。例如正则表达式\<the\>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。 |
| \> | 匹配词(word)的开始(\<)和结束(\>)。例如正则表达式\<the\>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。 |
| ( ) | 将( 和 ) 之间的表达式定义为"组"(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。 |
| | | 将两个匹配条件进行逻辑"或"(or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。 |

正则表达式语法支持情况

|----------------|-------|-----------|--------|-------|-------------|-------------------------------------|-------|-------|--------|---------|
| 命令或环境 | . | | ^ | $ | \( \) | \{ \} | ? | + | | | ( ) |
| vi | √ | √ | √ | √ | √ | | | | | |
| Visual C++ | √ | √ | √ | √ | √ | | | | | |
| awk | √ | √ | √ | √ | | awk是支持该语法的,只是要在命令 | √ | √ | √ | √ |
| awk | √ | √ | √ | √ | | 行加入 --posix or --re-interval参数即可,可见 | √ | √ | √ | √ |
| awk | √ | √ | √ | √ | | man awk中的interval expression | √ | √ | √ | √ |
| sed | √ | √ | √ | √ | √ | √ | | | | |
| delphi | √ | √ | √ | √ | √ | | √ | √ | √ | √ |
| python | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
| java | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |
| javascript | √ | √ | √ | √ | √ | | √ | √ | √ | √ |
| php | √ | √ | √ | √ | √ | | | | | |
| perl | √ | √ | √ | √ | √ | | √ | √ | √ | √ |
| C# | √ | √ | √ | √ | √ | √ | √ | √ | √ | √ |

应用教学

大家可以使用Nodepad++来练习。

按下Ctrl+F,弹出搜索替换窗口,Search Mode项点Regular expression即可。

输入【.】123abc匹配了6次,说明每个字符都匹配了一次。

如果想知道有多少数字,输入【0-9】即可。

如果想知道连续三个数字有几处,,输入【\d{3}】即可。

实例应用

1.验证用户名和密码:("^a-zA-Z\w{5,15}$")正确格式:"A-Za-z_0-9"组成,并且第一个字必须为字母6~16位;

2.验证电话号码:("^(\d{3,4}-)\d{7,8}$")正确格式:xxx/xxxx-xxxxxxx/xxxxxxxx;

3.验证手机号码(包含虚拟号码和新号码段):"^1(380-9|45-9|50-3,5-9|66|70-8|989)0-9{8}$";

4.验证身份证号(15位):"\d{14}\[0-9,0-9xX]",(18位):"\d{17}(\d|X|x)";

5.验证Email地址:("^\w+(-+.\w+)*@\w+(-.\w+)*\.\w+(-.\w+)*$");

6.只能输入由数字和26个英文字母组成的字符串:("^A-Za-z0-9+$");

7.整数或者小数:^0-9+(.0-9+){0,1}$

8.只能输入数字:"^0-9*$"。

9.只能输入n位的数字:"^\d{n}$"。

10.只能输入至少n位的数字:"^\d{n,}$"。

11.只能输入m~n位的数字:"^\d{m,n}$"。

12.只能输入零和非零开头的数字:"^(0|1-90-9*)$"。

13.只能输入有两位小数的正实数:"^0-9+(\.0-9{2})?$"。

14.只能输入有1~3位小数的正实数:"^0-9+(\.0-9{1,3})?$"。

15.只能输入非零的正整数:"^\+?1-90-9*$"。

16.只能输入非零的负整数:"^\-1-90-9*$"。

17.只能输入长度为3的字符:"^.{3}$"。

18.只能输入由26个英文字母组成的字符串:"^A-Za-z+$"。

19.只能输入由26个大写英文字母组成的字符串:"^A-Z+$"。

20.只能输入由26个小写英文字母组成的字符串:"^a-z+$"。

21.验证是否含有^%&',;=?\\"等字符:"\[%\&',;=?\\^]+"。

22.只能输入汉字:"^\\u4e00-\\u9fa5{0,}$"。

23.验证URL:"^http://(\\w-+\.)+\\w-+(/\\w-./?%\&=*)?$"。

24.验证一年的12个月:"^(0?1-9|1[0-2](https://baike.baidu.com/item/0-2/58505032?fromModule=lemma_inlink "0-2"))$"正确格式为:"01"~"09"和"10"~"12"。

25.验证一个月的31天:"^((0?1-9)|((1|2)0-9)|30|31)$"正确格式为;"01"~"09"、"10"~"29"和"30"~"31"。

26.获取日期正则表达式:\\d{4}年\|\\-\|\\.\d{\1-\12}月\|\\-\|\\.\d{\1-\31}日?

评注:可用来匹配大多数年月日信息。

27.匹配双字节字符(包括汉字在内):\^\\x00-\\xff

评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

28.匹配空白行的正则表达式:\n\s*\r

评注:可以用来删除空白行

29.匹配HTML标记的正则表达式:<(\S*?)\^\>*>.*?</>|<.*? />

评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力

30.匹配首尾空白字符的正则表达式:^\s*|\s*$

评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式

31.匹配网址URL的正则表达式:a-zA-z+://\^\\s*

评注:网上流传的版本功能很有限,上面这个基本可以满足需求

32.匹配账号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^a-zA-Za-zA-Z0-9_{4,15}$

评注:表单验证时很实用

33.匹配腾讯QQ号:1-90-9{4,}

评注:腾讯QQ号从10 000 开始

34.匹配中国邮政编码:1-9\\d{5}(?!\d)

评注:中国邮政编码为6位数字

35.匹配ip地址:(1-9{1,3}\.){3}1-9

评注:提取ip地址时有用

36.匹配MAC地址:(A-Fa-f0-9{2}\:){5}A-Fa-f0-9

相关推荐
Patrick在香港12 小时前
Python正则表达式实战:解析和验证香港身份证、车牌、电话格式
开发语言·python·正则表达式
吴声子夜歌2 天前
正则指引——Ruby
开发语言·正则表达式·ruby
吴声子夜歌2 天前
正则指引——Golang
开发语言·golang·正则表达式
吴声子夜歌4 天前
正则指引——PHP
开发语言·正则表达式·php
吴声子夜歌5 天前
正则指引——断言
正则表达式
吴声子夜歌6 天前
正则指引——匹配原理
java·正则表达式
吴声子夜歌7 天前
正则表达式——环视
开发语言·正则表达式
吴声子夜歌7 天前
正则表达式——边界
正则表达式
营养充电站8 天前
C++23 新特性在 CLion 中的实战体验
macos·docker·jupyter·正则表达式