10.1.2 基础的正则表达式
上一节在介绍什么是正则表达式的时候,我们第一次看到了\<hello\>,其中的\<和\>就是正则表达式中的两个特殊字符,也叫做元字符,它代表的意思是一个单词开始或结束的位置。下面将进一步介绍其他的一些元字符,以加深大家对正则表达式的理解。
1.“.”(一个点)符号
点符号用于匹配除换行符之外的任意一个字符。例如:r.t可以匹配rot、rut,但是不能匹配root,若使用r..t就可以匹配root、ruut、rt(中间是两个空格)等。下面的例子是从etcpasswd中搜索出“包含r,紧跟着两个字符,后面再接t”的行。
- [root@localhost ~]# grep 'r..t' etcpasswd
- root:x:0:0:root:/root:/bin/bash
- operator:x:11:0:operator:/root:/sbin/nologin
- ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
2.“*”符号
“”符号用于匹配前一个字符0次或任意多次,比如ab,可以匹配a、ab、abb等。“”号经常和“.”符号加在一起使用。比如“.”代表任意长度的不包含换行的字符。下面的例子是试图找到连续的r字母紧跟着字母t的行。由于在etcpasswd中没有rt、rrt这样的匹配,所以该表达式实际上只找出了包含t的行(r匹配了0次)。
- [root@localhost ~]# grep 'r*t' etcpasswd
- root:x:0:0:root:/root:/bin/bash
- shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
- halt:x:7:0:halt:/sbin:/sbin/halt
- news:x:9:13:news:etcnews:
- operator:x:11:0:operator:/root:/sbin/nologin
- ......(
- 略去内容)......
- xfs:x:43:43:X Font Server:etcX11/fs:/sbin/nologin
如果把上面的‘rt’换成‘r.t’,代表查找包含字母r,后面紧跟任意长度的字符,再跟一个字母t的行。如下所示:
- [root@localhost ~]# grep 'r.*t' etcpasswd
- root:x:0:0:root:/root:/bin/bash
- operator:x:11:0:operator:/root:/sbin/nologin
- ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
- vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
- rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin
- pcap:x:77:77::/var/arpwatch:/sbin/nologin
- sshd:x:74:74:Privilege-separated
- SSH:/var/empty/sshd:/sbin/nologin
- avahi-autoipd:x:100:101:avahi-autoipd:/var/lib/avahi-autoipd:/sbin/nologin
- xfs:x:43:43:X Font Server:etcX11/fs:/sbin/nologin
3.“{n,m}”符号
虽然“*”可用于重复匹配前一个字符,但却不能精确地控制匹配的重复次数,使用“{n,m}”符号则能更加灵活地控制字符的重复次数,典型的有以下3种形式:
·{n}匹配前面的字符n次。下例匹配的是包含root的行(r和t中包含两个o)。
- [root@localhost ~]# grep 'ro\{2\}t' etcpasswd
- root:x:0:0:root:/root:/bin/bash
- operator:x:11:0:operator:/root:/sbin/nologin
·{n,}匹配前面的字符至少n次以上(含n次)。
- [root@localhost ~]# grep 'ro\{0,\}t' etcpasswd
- root:x:0:0:root:/root:/bin/bash
- operator:x:11:0:operator:/root:/sbin/nologin
- vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
- rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin
·{n,m}匹配前面的字符n到m次。
4.“^”符号
这个符号位于键盘数字6的上面,又称尖角号。这个符号用于匹配开头的字符。比如说“^root”匹配的是以字母root开始的行。
- [root@localhost ~]# grep '^root' etcpasswd
- root:x:0:0:root:/root:/bin/bash
5.“$”符号
和上面的尖角号相对,“$”用于匹配尾部,比如说“abc$”代表的是以abc结尾的行。如果是“^$”则代表该行为空,因为^和$间什么都没有。下例匹配的是以r开头,中间有一串任意字符,以h结尾的行。
- [root@localhost ~]# grep '^r.*h$' etcpasswd
- root:x:0:0:root:/root:/bin/bash
6.“[]”符号
这是一对方括号,用于匹配方括号内出现的任一字符。比如说单项选择题的答案,可能是A、B、C、D选项中的任意一种,用正则表达式表示就是[ABCD]。如果遇到比较大范围的匹配,比如说要匹配任意一个大写字母,就需要使用“-”号做范围限定,写成[A-Z],要匹配所有字母则写成[A-Za-z]。一定要注意,这里“-”的作用不是充当一个字符。
如果是要匹配不是大写字母A、B、C、D的字符又该怎么写呢?还记得上面的“^”号吗,如果这个符号出现在[]中,则代表取反,也就是“不是”的意思。那这里的写法就是[^A-D],事情变得有点复杂了。
这里举个例子,看如何匹配手机号。手机号是11位连续的数字,第一位一定是1,所以表示为“^1”;第二位有可能是3(移动)或8(联通),表示为“[38]”;后面连续9个任意数字,表示为“[0-9]{9}”;所以整个表达式应该写为“^1[38][0-9]{9}”。
7.“\”符号
假设有个固定电话号码021-88888888,当然也可以写成021 88888888(区号和电话号码之间用空格隔开),它们的不同之处就是区号和电话号码之间使用的符号不同,一个是“-”,一个是空格。那么,对于这个电话号码要怎么匹配呢,很容易地想到应该使用“[]”来匹配。但是这么写:[-],对吗?答案是否定的,因为“-”放到“[]”中有特别的含义。为了表示其作为一个字符的本意,就要使用“\”符了。这个符号代表转义字符,我们可以对很多特殊的字符进行“转义”,让它只代表字符本身,因此这里的写法就应该是[\-]。
再举个例子,之前我们了解到“.”代表的是任意长度的不包含换行的重复字符。但是如果想要匹配任意长度的点号呢?这时使用转义字符就对了:“.”。如果想要对“\”符号进行转义,就可以这样写:“\”。
8.“\<”符号和“\>”符号
这两个符号分别用于界定单词的左边界和右边界。比如说“\<hello”用于匹配以“hello”开头的单词;而“hello\>”则用于匹配以“hello”结尾的单词。还可以使用它们的组合——“\<\>”用于精确匹配一个字符串。所以“\<hello\>”可精确匹配单词hello,而不是helloworld等。如下所示:
- [root@localhost ~]# echo "hello" | grep '\<hello\>'
- hello
- [root@localhost ]# echo "hellod" | grep '\<hello\>'
- [root@localhost ]# #
- 没有输出,表示匹配不成功
以上讲的是8种常见的元字符,还有些不太常用的字符,这些字符中有不少可以使用之前讲的8种基础的元字符来表示,所以笔者并不打算一一详细介绍,仅作一些列举和简单说明。
9.“\d”符号
匹配一个数字,等价于[0-9],使用grep匹配这种正则表达式时可能会遇到无法匹配的问题。示例如下:
- #123
- 是一个数字,用[0-9]
- 匹配成功
- [root@localhost ]# echo 123 | grep [0-9]
- 123
- #
- 但是用这种方式却匹配不成功
- [root@localhost ]# echo 123 | grep '\d'
- [root@localhost ]# #
- 没有输出,表示匹配不成功,为什么呢?
- #
- 这是因为“\d
- ”是一种Perl
- 兼容模式的表达式,又称作PCRE
- ,要想使用这种模式的匹配符,
- 需要加上-P
- 参数
- [root@localhost ]# echo 123 | grep -P '\d'
- 123 #
- 这样就匹配成功了
10.“\b”符号
匹配单词的边界,比如“\bhello\b”可精确匹配“hello”单词。
- [root@localhost ]# echo "hello world" | grep 'hello'
- hello world
- [root@localhost ]# echo "helloworld" | grep '\bhello\b'
- [root@localhost ~]# #
- 这里没有匹配
11.“\B”符号
匹配非单词的边界,比如hello\B可以匹配“helloworld”中的“hello”。
- [root@localhost ~]# echo "helloworld" | grep 'hello\B'
- helloworld
12.“\w”符号
匹配字母、数字和下划线,等价于[A-Za-z0-9]。
- [root@localhost ]# echo "a" | grep '\w'
- a
- [root@localhost ]# echo "\\" | grep '\w'
- [root@localhost ~]# #
- 这里没有匹配
13.“\W”符号
匹配非字母、非数字、非下划线,等价于[^A-Za-z0-9]。
- [root@localhost ~]# echo "\\" | grep '\W'
- \ #
- 匹配\
- 符号
14.“\n”符号
匹配一个换行符。
15.“\r”符号
匹配一个回车符。
16.“\t”符号
匹配一个制表符。
17.“\f”符号
匹配一个换页符。
18.“\s”符号
匹配任何空白字符。
19.“\S”符号
匹配任何非空白字符。