在本章中你将看到如何处理字符集合。不像“
.
”符号仅仅是匹配特定的单个字符(前一章中学到的),集合可以使得选择更多字符,或者是一个字符区间。
匹配几个字符
在上一节已经学习到,“
.
”可以用来匹配任何一个字符。在上一节的最后一个例子中,“
.a
”用来匹配“
na
”和“
sa
”,也就是说“
.
”匹配了“
n
”和“
s
”。假设现在还有一个名为“
ca1.xls
”的文件,那如何继续只是匹配
na
和
sa
呢?因为“
.
”能够匹配
c
,所以这个文件名也会被匹配。
为了能够匹配
n
或者
s
而不包括其他字符,则你可能只是想匹配这两个字符。在正则表达式中,匹配一组定义好的字符可以使用“
[
”“
]
”元字符。在这两个元字符之间的字符组,都可以作为一个匹配字符(但是不是全部)。
下面是对上个例子的一个修改版本:
文本
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
正则表达式
[ns]a.\.xls
结果
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
分析
这里的正则表达式是使用
[ns]
开始的。这将匹配
n
或者
s
(而不是
c
或者其他字符)。
[
和
]
则不匹配任何字符,这里用来定义集合。
a
匹配字面意义上的
a
,“
.
”则匹配任何一个字符,“
\.
”匹配“
.
”,而
xls
匹配字面意义上的
xls
。当使用此模式的时候,只有期望的文件名才会匹配。
注意:实际上[ns]a.\.xls也不是很准确。如果有一个
usa1.xls
的文件,也将会匹配。解决这个问题的方法涉及到位置匹配,将在第六章中介绍。
就如你所看到的,测试一个正则表达式实际上是很复杂的。检测一个模式是否匹配你想要的这是很容易的。最大的挑战在于是否不想要的就不会匹配上。
字符组一般可以用于不考虑大小写的搜索功能中,如下例:
文本
The
phrase "regular expression" is often
abbreviated as RegEx or regex.
正则表达式
[Rr]eg[Ee]x
结果
The phrase "regular expression" is often
abbreviated as RegEx
or regex
.
分析
这里使用的模式包含了两个字符组:
[Rr]
匹配
R
和
r
,
[Ee]
匹配
E
和
e
。这样,
RegEx
和
regex
都是匹配的。尽管如此,
REGEX
还是不能匹配。
如果你只是想使用不区分大小写的匹配,上面的技术实际上是没有必要的。这种匹配方式只是在部分不区分大小写的时候有用。
使用字符组区间
让我们重新来看上面的例子。最后使用的模式,[ns]a.\.xls,还有一个问题。如果有一个文件名为sam.xls怎么办?这也同样可以匹配,因为“
.
”匹配所有的字符,而不仅仅是数字。
下面使用字符组来解决这个问题:
文本
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
正则表达式
[ns]a[0123456789]\.xls
结果
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
分析
在这个例子中,模式被修改成第一个字母必须是
n
或者
s
,而第二个字母必须是
a
,地三个字母则需要是数字(
[0123456789]
)。注意到最后的
sam.xls
并没有被匹配,这是因为字母
m
不匹配任何数字字符。
在使用正则表达式的时候,你可能会发现需要经常指定字符的范围(如
0
到
9
,
A
到
Z
)。为了简化字符区间的使用,正则表达式提供了一个特殊的元字符:
-
(连字符),用来指示区间。
下面是一个相同的例子,只是这次采用了区间的方式:
文本
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
正则表达式
[ns]a[0-9]\.xls
结果
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
分析
模式
[0-9]
和模式[0123456789]的功能是一样的,所以当然结果也是一样的。
区间不仅仅限于数字。下面的都是合法的区间:
-
A-Z
匹配所有的
A
到
Z
的大写字符。
-
a-z
匹配所有的
a
到
a
的小写字符。
-
A-F
匹配A到F的大写字符。
-
A-z
匹配从
ASCII A
到
ASCII z
的所有字符(你可能从来没有用过这个模式,因为这个模式不仅仅匹配所有字母,还匹配包含在
ASCII
表中
A
到
z
中的字符,如
[
和
^
等)。
任何两个字符都可以作为区间的开始和结束。实际上,区间总是一些数字或者字符的集合。
需要注意的是,提供的区间不要结束的字符
ASCII
码比开始的
ASCII
码字还小,如
[3-1]
。这将不能工作,而且经常使得整个模式不能工作。
另外,
-
(连字符)仅仅只是在区间中才是元字符。而在集合之外,
-
则是字面上的意思,匹配“
-
”,此时没有必要进行转义。
可以在一个集合中使用多个字符区间。如下面的模式匹配所有的大小写字母和数字。
[A-Za-z0-9]
这个模式实际上是下面的简写:
[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890]
就像你所看到的,区间使得正则表达式更加简洁。
下面是一个查找
RGB
值的例子(颜色通过十六进制的表示法,用来表示红色、绿色和蓝色的分量)。在
Web
页面上,
RGB
值被指定为#000000 (黑), #FFFFFF (白), #FF0000
(红)等等。
RGB
值可以为大写或者小写,所以#FF00ff (品红) 也是合法的。下面是个例子:
文本
<BODY
BGCOLOR="#336633" TEXT="#FFFFFF"
MARGINWIDTH="0"
MARGINHEIGHT="0"
TOPMARGIN="0"
LEFTMARGIN="0">
正则表达式
#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]
结果
<BODY BGCOLOR="#336633
"
TEXT="#FFFFFF
"
MARGINWIDTH="0"
MARGINHEIGHT="0"
TOPMARGIN="0"
LEFTMARGIN="0">
分析
这个模式中,包含了“
#
”作为字面字符,然后是六个重复的[0-9A-Fa-f]字符集合。这将匹配
#
后接六个字符,其中每个都必须是数字或者
A
到
F
(无论是大写还是小写)。
非字符集的匹配
字符集合一般用于指定一组需要匹配的字符。但是有些时候,你的需求刚好相反——一组你不想匹配的字符。换句话说,任何字符除了这里定义的。
可以通过穷举所有想要的字符来做匹配(当需要的字符很多的时候长度将会很长),可以通过对于字符集合的否定来实现。下面是个例子:
文本
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
正则表达式
[ns]a[^0-9]\.xls
结果
sales1.xls
orders3.xls
sales2.xls
sales3.xls
apac1.xls
europe2.xls
sam.xls
na1.xls
na2.xls
sa1.xls
ca1.xls
分析
这里的模式和前面一个例子中的完全相反。
[0-9]
匹配所有的数字,而
[^0-9]
则匹配所有的非数字。也就是说,[ns]a[^0-9]\.xls可以匹配sam.xls,但不能匹配na1.xls,
na2.xls
或者 sa1.xls。
注意,^字符是将字符集合中的所有字符都取消匹配,而不仅仅只是此字符后的字符。
小结
元字符“
[
”和“
]
”用来定义一组字符,其中的每个字符都可以匹配。字符集合可以通过枚举,也可以通过元字符“
-
”来指定区间。字符集合还可以通过“
^
”来否定,这使得模式可以匹配除字符集合中的所有字符。
分享到:
相关推荐
最重要的是——请给我30分钟,如果你没有使用正则表达式的经验,请不要试图在30秒内入门——除非你是超人 :) 别被下面那些复杂的表达式吓倒,只要跟着我一步一步来,你会发现正则表达式其实并没有你想像中的那么困难...
3.10 如果我不使用表达式的值, 我应该用++i 或i++ 来自增一个变量 吗? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 3.11 为什么如下的代码int a = 100, b = 100; long int c = a * b;...
### 跟我学写Makefile #### 概述与目的 本文档旨在通过系统而详尽的方式指导读者学习如何编写Makefile。Makefile是一种用于自动化构建过程的脚本文件,广泛应用于软件开发中,特别是在大型项目的编译过程中。通过...
该命令表示把源串内的match都替换成replace,s指示match可以是正则表达式。 g表示把每行内所有match都替换,如果去掉g,则只有每行的第1处match被替换(实际上不需要g,因为一个.d文件中,只会在开头有一个main.o:)。...
o 7.7 有人跟我讲, 数组不过是常指针。 o 7.8 我遇到一些 ``搞笑" 的代码, 包含 5["abcdef"] 这样的 ``表达式"。 这为什么是合法的 C 表达式呢 ? o 7.9 既然数组引用会蜕化为指针, 如果 arr 是数组, 那么 arr 和...
6.9 有人跟我讲,数组不过是常指针。这样讲准确吗? 6.10 我还是很困惑。到底指针是一种数组,还是数组是一种指针? 6.11 我看到一些“搞笑”的代码,包含5["abcdef"]这样的“表达式”。这为什么是合法的C语言...
1.27 我的编译器总在报函数原型不匹配的错误,可我觉得没什么问题。这是为什么? 15 1.28 文件中的第一个声明就报出奇怪的语法错误,可我看没什么问题。这是为什么? 15 1.29 为什么我的编译器不允许我定义大数...