1.1. 基本语法
通过一张图表来对正则表达式的基本进行一个回顾
single char | quantifiers(位置) | Column C |
---|---|---|
d 匹配数字 | * 0个或者更多 | ^一行的开头 |
w 匹配word(数字、字母) | 1个或更多,至少1个 | $一行的结尾 |
W 匹配非word(数字、字母) | ? 0个或1个,一个Optional | b 单词"结界"(word bounds) |
s 匹配white space(包括空格、tab等) | {min,max}出现次数在一个范围内 | C3 |
S 匹配非white space(包括空格、tab等) | 匹配出现n次的 | C3 |
. 匹配任何,任何的字符 | B3 | C3 |
1.1.1. single char
假设你有一段字符如下:
w
将匹配所有word,当然,() - 等字符除外
www
发现匹配的有'The
se are
som
e pho
ne number
s ...'
注意正则表达式是匹配一个连续串的规则,所以可以看到三个字母的单词可以匹配到,6个单词的也可以匹配到。
ss
匹配到一行中连续两个空格
quantifiers
假设我们有这一段话:
代码语言:javascript复制The colors of the rainbow have many colours
and the rainbow does not have a single colour.
我们想把所有的颜色找出来colors
colours
colour
答案 colou?rs?
嗯,看起来很简单,很方便。
好了,现在想要匹配一行中的4个数字,或者一行中的5个字母等,这时候用quantifiers就非常方便了。
我现在想找5个字母组成的单词
-
w{5}
这样可以吗?嗯..不行的,看下它匹配的内容,如下: 'These
are somephone
numbe
rs 915-555-1234...' 的确,我们模板给的很简单,它只找一行中,连续出现5个字母的序列。所以现在改进一下好了 -
w{5}s
为了能找到单词,所以我希望5个字母后,跟一个空格的序列,这样应该可以了吧,看下匹配情况: 'These
are somephone
numbers
915-555-1234...' 嗯,是的,只有目前这些方法,是做不到的。 所以,我们需要第三个工具 "position"
1.1.2. position
回到刚才的问题之前,先熟悉下^
$
和 b
This is somthing
is about
a blah
words
sequence of words
Hello and
GoodBye and
Go gogo!
来看下各种正则所匹配的内容
-
w
这个应该毫无疑问,匹配所有的words -
^w
多了一个^
,这样子,就只能匹配到每一行开头的单词了This
is
a
words
sequence
Hello
GoodBye
Go
-
w $
这样就能匹配到每行的最后一个字母
回到刚才的问题
现在想找5个字母组成的单词
就变得很简单了,使用单词结界符b
答案就是bw{5}b
1.1.3. 找个电话号码吧
最后,找一个刚才出现的电话号123-456-1231
用以上最基本的正则方法就是 d{3}-d{3}-d{4}
,这样就找到了。 但是有的时候,电话号码是123.456.1234
或者 (212)867-4233
的结构怎么办呢?
正则表达式中的或
或者其他表达方式,下面一一来介绍。
1.2. 字符分类(char class)
前面记录了最基本的方法,接下来说一下分类符[]
这个符号用来表示逻辑关系或
,比如[abc]
表示a或者b或c.[-.]
表示符号-
或者.
号(注意这里,在[]
中的.
号代表的就是这个符号,但是如果在其外面,表示个匹配所有。 所以如果不在[]
之中,想要匹配'.',就要通过转意符号.
)
1.2.1. 分类的简单应用
字符序列:
代码语言:javascript复制The lynk is quite a link don't you think? l nk l(nk
正则表达式:
l[yi (]k
结果:
代码语言:javascript复制lynk link l nk l(nk
很容易理解的,就是表达或
逻辑。
1.2.2. 匹配所有可能的电话号码
好了,现在回到之前遗留的问题,有以下字段,请匹配所有可能的电话号码:
代码语言:javascript复制These are some phone numbers 915-134-3122. Also,
you can call me at 643.123.1333 and of course,
I'm always reachable at (212)867-5509
好的,一步一步来,刚才我们使用d{3}-d{3}-d{4}
匹配了连字符的情况。现在我们可以很轻松的把.
这种情况加进去了
第一步: d{3}[-.]d{3}[-.]d{4}
第二步: 为了能够匹配括号,可以使用?来,因为这是一个option选择。所以最后就成了
(?d{3}[-.)]d{3}[-.]d{4}
这里还是要说明,在[]中,特殊字符不需要转义,可以直接使用,比如[.()]
,但是在外面,是需要转义的(
.
等
1.2.3. []的特殊语法
刚才介绍了最简单和基本的功能,但是有些特殊的地方需要注意
- -连接符不是第一个字符时
[-.]
的含义是连字符-
或者点符.
。 但是,如果当连字符不是第一个字符时,比如[a-z]
,这就表示是从字母a到字符z。 - []中的^
^
在之前介绍中,是表示一行开头,但是在[]
中,有着不同的含义。[ab]
表示a或者b[^ab]
啥都行,只要不是a或b(anythings except a and b),相当于取反
1.2.4. []和()
除了使用[]
表示或逻辑,()
也是可以的。用法是(a|b)
表示a或者b
比如下面的例子,匹配所有email
代码语言:javascript复制gaoyaqi411@126.com
dyumc@google.net
sam@sjtu.edu
思路:
首先要想我到底相匹配什么,这里我想匹配的是
- 任何一个以words开头的,一个或更多
w
- 紧接着是一个
@
符号w @
- 接着有一个或者更多的words
w @w
- 接着一个
.
标点w @w .
- 接着一个
com
net
或edu
w @w .(com|net|edu)
还是提醒注意第四步的.
转义符号
好了,这样几可以匹配以上的所有邮箱了。但是还有一个问题,因为邮箱用户名是可以有.
的,比如vincent.ko@126.com
其实仍然很简单,修复如下:
[w.] @w .(com|net|edu)
1.2.5. 总结
[]
的作用,用英文表达就是"alternation",表达一个或的逻辑;/[-.(]/
在符号中的连字符-
放在第一位表示连字符本身,如果放在中间,表示"从..到..",比如[a-z]
表示a-z[.)]
括号中的特殊符号不需要转义,就表示其本身[^ab]
括号中的^
表示非,anythings excepta
andb
(a|b)
也可表示选择,但是它有更强大的功能....
所以,()
的强大功能是什么呢? 分组捕获,这对序列的替换、交换是很有帮助的。 后面一节进行学习记录
1.3. 分组捕获(capturing groups)
什么是分组捕获,现在回到之前电话号码的例子
代码语言:javascript复制212-555-1234
915-412-1333
//我想要保留区号,把后面的电话号码变为通用性的