一直感觉正则表达式很神奇,非常强大,但并没有系统学习过,今天抽空过一遍,希望能够彻底掌握它
简介
正则表达式在处理文本信息时非常有用,不限于代码、日志文件、文档等。在开始学习正则之前,需要有这种概念:任何文本都是由单个字符组成。
语法
简单匹配
abcdefg、abcde、abc这三个字符串,用正则abc可以匹配前面三个串的abc字段
abc123xyz、define”123”、var g=123,用正则123可以匹配三个公共的123数字
简单语法
\d 匹配任何0~9的数字;\D匹配任意非数字0~9的字符
.
表示通配符,可以匹配任意字符。如果要匹配.
,可以加入转义符\.
Task | Text |
---|---|
Match | cat. |
Match | 896. |
Match | ?=+. |
Skip | abc1 |
上面的例子,正则...\.
匹配前三个,最后一个不匹配
匹配特定的字符,使用[]
Task | Text |
---|---|
Match | can |
Match | man |
Match | fan |
Skip | dan |
Skip | ran |
Skip | pan |
上面的例子,需要匹配前三个,后三个不匹配,可用正则[cmf]an
。[cmf]表示只匹配cmf之中的任意一个。
剔除特定字符,使用[^…]
Task | Text |
---|---|
Match | hog |
Match | dog |
Skip | bog |
上面的例子,需要匹配前练个,最后一个不匹配,可用正则[^b]og
,当然也可以用前面的匹配特定字符[hd]og
连续字符,使用-
如果要匹配26个小写字母,难道我们要吧26个字母全部列出来么?当然可以,但太二了不是么。正则表达式用-表示连续的字符。如0-6相当于[0123456]
Task | Text |
---|---|
Match | Ana |
Match | Bob |
Match | Cpc |
Skip | aax |
Skip | bby |
Skip | ccz |
上面的例子,匹配前三个,后三个不匹配,可用正则[A-c][n-p][a-c]
注意,大写和小写字母是不同的字符,需要分开处理
\w
相当于[A-Za-z0-9_],\W
相当于[^A-Za-z0-9_]
字符个数的匹配,使用{}
前面提到的额匹配都是单个字符的匹配,如果需要匹配3个数字,你也许会写成\d\d\d
,但实际上有更好的写法,比如\d{3}
。正则甚至支持范围,如a{1,3}表示最少有1个a,最多3个a。
Task | Text |
---|---|
Match | wazzzzzup |
Match | wazzzup |
Skip | wazup |
上面的例子,前两个匹配,最后一个不匹配,可用正则表达式waz{3,5}up
字符任意个数的匹配
*
表示大于等于0个
+
表示大于等于1个
比如,\d*表示任意个数字,但是\d+则表示最少要有一个数字
Task | Text |
---|---|
Match | aaaabcc |
Match | aabbbbc |
Match | aacc |
Skip | a |
上面的例子,前三个匹配,最后一个不匹配,可用正则aa+b*c+
标记某个字符可选,使用?
由于?
修饰的字符为可选,所以正则ab?c
可以匹配abc
或者ac
。
Task | Text |
---|---|
Match | 1 file found? |
Match | 2 files found? |
Match | 24 files found? |
Skip | No files found. |
上面的例子,前三个匹配,最后一个不匹配,可用正则\d+ files? found\?
空格、换行、对齐等字符
空格 制表符tab(\t) 换行(\n) 回车(\r)。可以用\s
来表示前面任意的空白符。同理,\S
与\s
相反,即各种空白符之外的字符。
Task | Text |
---|---|
Match | 1. abc |
Match | 2. abc |
Match | 3. abc |
Skip | 4.abc |
上面的例子,前三个匹配,最后一个不匹配,可用正则\d\.\s+abc
开始^和结束$
需要注意的是,这里的开始^
和例外[^...]
的意义是不同的。假如需要验证用户的输入是否为5-12位数字组成的QQ号码,可以用^\d{5,12}$
。
Task | Text |
---|---|
Match | Mission: successful |
Skip | Last Mission: unsuccessful |
Skip | Next Mission: successful upon capture of target |
上面的例子,第一个匹配,后两个不匹配,可用正则^Mission: successful$
匹配并分组(…)
正则表达式不仅仅可以用来匹配,还可以将匹配的结果进行分组group。
比如,我们可以用正则表达式^(IMG\d+\.png)$
找出所有照片,但是如果我们只需要照片名,不需要后缀名png呢,你会怎么做?这个时候可以用^(IMG\d+)\.png$
Task | Text |
---|---|
Capture | file_record_transcript.pdf |
Capture | file_07241999.pdf |
Skip | testfile_fake.pdf.tmp |
上面的例子,可用正则^(file.+)\.pdf$
当然,分组还支持嵌套,用于更复杂的多重分组。如下,匹配日期并且列出年份
Task | Text |
---|---|
Capture | Jan 1987 |
Capture | May 1969 |
Capture | Aug 2011 |
上面的例子,可用正则(\w+ (\d{4}))
条件匹配(…|…)
假如你让别人给你带早餐,但你又不确定早餐店还剩下什么,这时候你会给别人几个备选项,在正则里可以用(..|..)
来表示。如Buy more (milk|bread|juice)
Task | Text |
---|---|
Match | I love cats |
Match | I love dogs |
Skip | I love logs |
Skip | I love cogs |
上面的例子,可用正则I love (cats|dogs)
字符边界
通常用\b
表示字符的边界,与之相对的\B
。现有字符串Chapter 1
,可以用正则ter\b
匹配得到ter
,注意\b
的位置,如果正则写成\bter
则无匹配结果
练习
匹配浮点数
Task | Text |
---|---|
Match | 3.14529 |
Match | -255.34 |
Match | 128 |
Match | 1.9e10 |
Match | 123,340.00 |
Skip | 720p |
上面的例子,可用正则表达式^-?\d+(,\d+)*(\.\d+(e\d+)?)?$
匹配图片
Task | Text |
---|---|
Skip | .bash_profile |
Skip | workspace.doc |
Capture | img0912.jpg |
Capture | updated_img0912.png |
Skip | documentation.html |
Capture | favicon.gif |
Skip | img0912.jpg.tmp |
Skip | access.lock |
上面的例子,可用正则表达式(\w+)\.(jpg|png|gif)$
说明
本文参考链接regexone
文中的正则表达式只是示例,要达到同样的结果,正则表达式可能有多种写法