08 shell正则表达式



8.1  什么是正则表达式
所谓正则表达式,实际上就是用来描述某些字符串匹配规则的工具。由于正则表达式语法简练,功能强大,得到了许多程序设计语言的支持,包括Java、C++、Perl以及Shell等。对于初学者来说,首次接触正则表达式非常难以接受,本节将介绍正则表达式的入门知识,以利于后面几节的学习。
8.1.1  为什么使用正则表达式
在进行程序设计的过程中,用户会不可避免地遇到处理某些文本的情况。有的时候,用户还需要查找符合某些比较复杂规则的字符串。对于这些情况,如果单纯依靠程序设计语言本身,则往往会使得用户通过复杂的代码来来实现。但是,如果使用正则表达式,则会以非常简短的代码来完成。
8.1.2  如何学习正则表达式
1.重点在于理解元字符
2.掌握好正则表达式的语法
3.开拓思路,寻找最佳的表达方法
8.1.3  如何实践正则表达式
当一个正则表达式完成之后,并能够保证这个表达式一定是准确的,需要不断地测试才可以确定其正确与否。在不同的环境下,用户需要不同的工具来帮助他完成测试的过程。如果是在Shell命令行中,用户可以使用grep命令来测试。

8.2  正则表达式基础
通过前面的一节的学习,用户对于正则表达式应该有个初步的了解。本节将在前面一节的基础上,逐步介绍正则表达式的基础知识,主要是各种元字符及其使用方法。

8.2.1  正则表达式的原理
输入文本 -> 正则表达式 -> 符合规则的文本
              |
             不符合规则的文本

8.2.2  基本正则表达式
基本正则表达式(Basic Regular Expression,BRE),又称为标准正则表达式,是最早制订的正则表达式规范,仅支持最基本的元字符集。基本正则表达式是POSIX规范制订的两种正则表达式语法标准之一,另外一种语法标准称为扩展正则表达式,将在随后介绍。
基本正则表达式所定义的元字符主要有以下几种。
1.行首定位符“^”
是正则表达式中的定位符之一,用来匹配行首的字符,表示行首的字符是“^”后面的那个字符。正则表达式中的定位符的作用与其他的元字符不同,它们不是用来匹配具体的文本,而是匹配某个具体的位置,例如行首定位符“^”就是用来匹配文本行的开头的字符的。

#! /bin/bash

#列出/etc目录中的以字母po开头的文件
str=`ls /etc | grep "^po"`
echo "$str"

2.行尾定位符“$”
与行首定位符的作用恰恰相反,行尾定位符的作用是用来定位文本行的末尾的。从语法上讲,行尾定位符的位置也与行首定位符相反,行首定位符位于所作用的字符之前,而行尾定位符位于所作用的字符之后。

#! /bin/bash

#列出/etc目录中以conf结尾的文件名
str=`ls /etc | grep "conf$"`

echo "$str"

3.单个字符匹配“.”
圆点“.”用来匹配任意单个字符,包括空格,但是不包括换行符“\n”。当用户使用“.”符号后,意味着该位置一定有一个字符,无论它是什么字符。
#! /bin/bash

#列出所有的包含字符串“samba”的文件名
str=`ls /etc | grep "samba"`
echo "$str"
echo "==============================="
#列出包含字符串samba以及另外一个字符的文件名
str=`ls /etc | grep "samba."`

echo "$str"

4.限定符“*”
星号“*”是正则表达式中的限定符之一。限定符本身不代表任何字符,它是用来指定其前面的一个字符必须要重复出现多少次才能满足匹配。星号“*”表示匹配其前导字符的任意次数,包括0次。
#! /bin/bash

#筛选出以字符s开头,紧跟着1个字符s,任意个字符s的文件名
str=`ls /etc | grep "^sss*"`

echo "$str"

5.字符集匹配“[]”
方括号“[]”的功能比较特殊,它是用来指定一个字符集合的,其基本语法为:
[abc]
其中a、b和c表示任意的单个字符。如果某个字符串在方括号所在的位置上出现了方括号中的任意一个字符,都是满足匹配规则。另外,对于连续的数字或者字母,可以使用连字符“-”来表示一个范围,例如“[a-f]”表示匹配字母表中a到f中的任意一个字母。而“[0-9]”表示匹配任意单个数字。

#! /bin/bash

#筛选所有以字符r开头,并且紧跟着1个字符c的文本行
str=`ls /etc |grep "^rc"`
echo "$str"
echo "=============================="
#筛选所有以字符r开头,紧跟着1个字符为c,下面1个字符为单个数字的文本行
str=`ls /etc | grep "^rc[0-9]"`
echo "$str"

6.字符集不匹配“[^]”
前面已经介绍过行首定位符“^”和字符集匹配符“[]”。但是如果将这2个符号结合起来,则其意义会发生变化。符号“[^]”表示不匹配其中列出的任意字符,其语法如下:
[^abc]
其中a、b和c表示任意的单个字符。“[^]”符号的用法与符号“[]”的用法相同,不再举例说明。
除了前面介绍的6个元字符之外,在基本正则表达式中还定义了其他的一些元字符。这些元字符使用较少,语法较繁琐,且在扩展正则表达式和PERL正则表达式中都有替代的元字符,所以不再详细说明。表8-1列出了基本正则表达式的其他的元字符。

8.2.3  扩展正则表达式
扩展正则表达式(Extended Regular Expression,ERE)支持比基本正则表达式更多的元字符,但是扩展正则表达式对有些基本正则表达式所支持的元字符并不支持。8.2.2中介绍的元字符“^”、“$”、“.”、“*”、“[]”以及“[^]”这6个元字符在扩展正则表达式都得到了支持,并且其意义和用法都完全相同,不再重复介绍。接下来重点介绍一下在扩展正则表达式中新增加的一些元字符。

1.限定符“+”
前面已经介绍过行首定位符“^”和字符集匹配符“[]”。但是如果将这2个符号结合起来,则其意义会发生变化。符号“[^]”表示不匹配其中列出的任意字符,其语法如下:
[^abc]
其中a、b和c表示任意的单个字符。“[^]”符号的用法与符号“[]”的用法相同,不再举例说明。
除了前面介绍的6个元字符之外,在基本正则表达式中还定义了其他的一些元字符。这些元字符使用较少,语法较繁琐,且在扩展正则表达式和PERL正则表达式中都有替代的元字符,所以不再详细说明。表8-1列出了基本正则表达式的其他的元字符。

#! /bin/bash

#筛选以字符串“ss”开头,后面至少紧跟着1个字符“s”的文本行
str=`ls /etc | egrep "^sss+"`

echo "$str"

2.限定符“?”
问号“?”是另外一个限定符,它用来限定前面的字符最多只出现1次,即前面的字符可以重复0次或者1次。
#! /bin/bash

#筛选以字符串“ss”开头,后面跟着0或者1个s的文本行
str=`ls /etc | egrep "^sss?"`

echo "$str"

3.竖线“|”和圆括号“()”
竖线“|” 表示多个正则表达式之间“或”的关系,其语法为:
expression1|expression2|expression3|…|expressionn
圆括号“()”用来表示一组可选值的集合。竖线和圆括号经常在一起使用,表示一组可选值。
#! /bin/bash

#筛选含有字符串“ssh”、“ssl”或者以字符串“yum”开头的文本行
str=`ls /etc | egrep "(ssh|ssl|^yum)"`

echo "$str"

8.2.4  Perl正则表达式
正则表达式是Perl语言的一大特色。Shell中的grep和egrep命令都支持Perl正则表达式。Perl正则表达式的元字符与扩展正则表达式的元字符大致相同,扩展正则表达式中的元字符在Perl正则表达式中都得到了了支持。另外,Perl正则表达式还增加了一些元字符。下面对常用的增加的元字符进行介绍。

1.数字匹配\d
符号“\d”匹配从0到9中的任意一个数字字符,等价于表达式“[0-9]”。
#! /bin/bash

#筛选以字符串rc开头,紧跟着一个数字的问本行
str=`ls /etc | grep -P "^rc\d"`

echo "$str"

2.非数字匹配\D
符号“\D”和符号“\d”的作用恰好相反,后者是匹配一个0~9之间的单个数字字符,而前者则匹配一个非数字字符。“\D”等价于表达式“[^0-9]”。
3.空白字符匹配\s
符号“\s”匹配任何空白字符,包括空格、制表符以及换页符等,等价于表达式“[\f\n\r\t\v]”。
4.非空白字符匹配\S
符号“\S”匹配任何非空白字符,等价于表达式“[^\f\n\r\t\v]”。

8.2.5  正则表达式字符集
一个正则表达式就是由一系列字符组成的字符串。其中,包括元字符和普通字符。由于元字符和普通字符都有许多个,所以形成了元字符集和普通字符集这两个集合。
在正则表达式中,普通字符集中的字符只表示它们的字面涵义,不对其他的字符产生影响。正则表达式的最简单的形式就是只由普通字符集中的字符组成,不包含元字符。
正则表达式的字符集通常使用方括号表达式表示,例如:
[cC]hina
[^hello]
[a-zA-Z]
[0123456789]
[0-9]

8.3  正则表达式应用
本书在前面的2节中,详细介绍了正则表达式的基础知识。为了使得读者更加清楚如何使用正则表达式,本节将详细介绍正则表达式的相关应用。

8.3.1  匹配单个字符
在正则表达式中,可以用来匹配单个字符的表达式大致有4种,分别是单个一般字符、转义后的元字符、圆点“.”表达式以及方括号表达式。下面分别进行介绍。

1.单个一般字符
所谓一般字符,是指除了正则表达式中已经定义的元字符之外的所有字符,例如英文字符、数字、空白字符以及标点符号等。这些一般字符组正则表达式中都只是表达它们自身的字面意义,没有其他额外的意义。当需要匹配某个一般字符时,可以直接将该字符作为表达式或者是表达式的一部分。

2.转义后的元字符
在前面介绍基本正则表达式、扩展正则表达式以及Perl正则表达式的时候,都介绍了一些元字符。如果想要匹配这些元字符本身,则需要在这些字符的前面加上转义字符“\”。通过这样操作,可以关闭这些元字符的特殊意义,而只保留其字面意义。
例如,如果想要匹配圆点“.”就可以使用表达式“\.”。经过转义之后,这个表达式就表示一个圆点符号,而不是任意单个字符。如果想要匹配其他的元字符,例如问号“?”,同样可以使用表达式“\?”。

#! /bin/bash
str=`grep "." demo3.txt`
echo "$str"

3.圆点表达式
圆点“.”表示匹配任意单个字符,除了换行符之外。关于圆点表达式的使用方法,请参见例8-4,不再重复介绍。

4.方括号表达式
前面已经介绍过,方括号表达式用来表示一个可选字符的集合。尽管通常情况下,在方括号中含有多个字符,但是一次只能从这些字符中选择一个,因此,方括号表达式仍然表示的是匹配单个字符。例如,表达式“[abc]”就表示匹配字符“a”、“b”或者“c”中的任意一个。同时,这种表示方法也是最简单的一种形式,也就是直接将所要匹配的字符都在方括号中罗列出来。
如果在方括号中的字符列表前面加上符号“^”,则表示取反的意思。也就是说,不匹配方括号中列出来的任何一个字符。例如,表达式“[^abc]”表示不匹配“a”、“b”和“c”这3个字符中的任何一个。

8.3.2  匹配多个字符
接下来再介绍如何匹配多个字符。正则表达式可以使用多种方法来匹配多个字符,其中最简单的一种就是将多个字符按照指定的顺序拼接起来。

#! /bin/bash

#搜索字符串“matter”
str=`grep "matter" demo3.txt`

echo "$str"

#! /bin/bash

#匹配含有字符“o”,后面紧跟着字符“r”或者“u”的文本行
str=`grep "o[ru]" demo3.txt`

echo "$str"

#! /bin/bash

#匹配任意多个字符“o”
str=`grep "lo*king" demo3.txt`

echo "$str"

#! /bin/bash

#筛选符合格式的电话号码
str=`egrep "800-[[:digit:]]{3}-[[:digit:]]{4}$" demo4.txt`

echo "$str"

8.3.3  匹配字符串的开头或者结尾

在正则表达式中,用户可以通过定位符来对字符串开头或者结尾进行匹配,定位符又称为锚点。一共有2个定位符,分别为行首定位符“^”和行尾定位符“$”。前者用来匹配文本行的开头字符,后者用来匹配文本行的结尾字符。
如果行首定位符和行尾定位符一起使用,则这2个符号之间的表达式就匹配整个字符串或者文本行。如果“^”符号后面紧跟着“$”符号,即“^$”则表示一个空行。因为行首后面紧跟着行尾,行中没有任何字符。

#! /bin/bash

#筛选以3个数字开头的文本行
str=`egrep "^[[:digit:]]{3}" demo5.txt`

echo "$str"

8.3.5  子表达式
所谓子表达式,是指由多个普通字符或者元字符组成的一个小的正则表达式。与正则表达式一样,子表达式本身也是一个完整的表达式,但是在使用时,子表达式是作为一个大的正则表达式的一部分来使用的,而不是单独使用。在正则表达式中,子表达式作为一个整体来看待。子表达式使用圆括号()括起来。

#! /bin/bash

str=`egrep " {2}" html.txt`
echo "$str"

#! /bin/bash

#匹配IP地址
str=`egrep "^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$" ip.txt`

echo "$str"

#! /bin/bash

#匹配IP地址
str=`egrep "^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$" ip.txt`

echo "$str"

8.3.6  通配符
Shell使用了正则表达式中的某些元字符作为其通配符,常用的有*、?、[]、{}以及^等。这些字符在Shell中的意义与在正则表达式中的意义有些区别,例如*表示匹配任意的字符,而非正则表达式中的限制其前导字符的0次或者多次重复。?表示一个字符,而非其前导字符的0次或者1次重复。

8.4  grep命令
在Shell的命令中,grep命令是一个与正则表达式关系非常密切,并且使用也非常频繁的命令。在本章的绝大部分例子中,都使用了grep命令来讲解。为了使读者掌握这个命令的使用方法,本节将对其进行详细介绍。

8.4.1  grep命令的基本语法
grep命令的名称来自于全局搜索正则表达式并打印文本行(Global Search Regular Expression and Print out the line)的缩写。它是一个非常古老的UNIX命令,也是一种强大的文本搜索工具。grep命令使用正则表达式来搜索文本,并且把匹配的文本行打印出来。
grep命令的基本语法如下:
grep [options] pattern [file…]
在上面的语法中,options表示选项,如表8-3所示。pattern表示要匹配的模式,file表示一系列的文件名。grep命令会从一个或者多个文件中搜索满足指定模式的文本行,并且打印出来。模式后面的所有的字符串参数都被看作是文件名。

8.4.2  grep命令族简介
随着UNIX的发展,grep命令也在不断地完善。
到目前为止,grep命令族已经包括grep、egrep以及fgrep等3个命令。egrep和fgrep命令只跟grep命令有很少的区别。
其中,egrep命令是grep命令的扩展,它使用扩展正则表达式作为默认的正则表达式引擎,因此,egrep命令支持更多的元字符。
fgrep命令是fixed grep或者fast grep的缩写。在fgrep命令中,所有的字母都看作是单词,也就是说,在fgrep命令中,所有的正则表达式中的元字符都将作为一般字符,仅仅拥有其字面意义,不再拥有特殊意义。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值