学习正则表达式

一直感觉正则表达式很神奇,非常强大,但并没有系统学习过,今天抽空过一遍,希望能够彻底掌握它

简介

正则表达式在处理文本信息时非常有用,不限于代码、日志文件、文档等。在开始学习正则之前,需要有这种概念:任何文本都是由单个字符组成

语法

简单匹配

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

文中的正则表达式只是示例,要达到同样的结果,正则表达式可能有多种写法

存粹没事瞎折腾 ヾ(≧▽≦*)o