shell脚本【符号9】正则表达式

本篇博客内容:

        一:正则和通配符的区别

        二:正则表达式运用场景

        三:正则表达式的相关说明

        四:正则表达式的介绍(重点)

                4.1  基本正则表达式

                4.2  扩展正则表达式

                4.3  POSIX字符集


正文:

1  正则表达式和Bash Shell通配符区别

    在前一节认识了通配符后,就能发现“通配符”和“正则表达式”还是挺像的。但是,有一点必须要知道:Bash Shell中的通配符和正则表达式是完全不同的两个东西,只是在某些符号和某些释义上有交叉而已。

    Bash Shell本身是不支持正则表达式的,它的语法也解释不了正则表达式,同时Bash Shell中的通配符不依据正则表达式标准。

 

    问1:既然Bash Shell中不支持正则表达式,为什么输入命令时,会有正则表达式的出现?

    答:虽然Bash Shell命令行解释器本身解释不了正则表达式,但是在bash shell的工具中,有的是支持正则表达式标准的,比如,vi、grep、sed、awk等工具。这些正则表达式最终不是由Bash命令行解释器进行解释的,而是在某一个工具中进行解释。

    需要明白的是,支持正则表达式的不是bash shell解释器本身,而是bash shell调用的其中的某些工具。

 

    问2:既然在Bash shell中既可以输入通配符,又可以输入正则表达式,那么一般是按照哪种来解释的?

    答:一条命令输入后,肯定是要先经过shell解析(解析过程,参考:点击打开链接)。

       比如命令:grep --color -n  "[a-zA-Z]*"  fil*

      会先对“fil* ”进行文件名匹配,而这个*就是由shell解析的,所以是被理解为通配符。

      如果只有一个file是匹配的;那么经过shell解析后的命令形式就是:

        grep --color -n [a-zA-Z]*  file

       然后就是执行grep命令,[a-zA-Z]*是提交给grep解析,这就是为什么在它两边需要加双引号的原因。是为了防止shell对该式进行错误的通配符式的文件名匹配。

       所以,如果是正则表达式,确定是要提交给具体命令进行解析,而不是通过shell进行通配符匹配的,要加上双引号或者单引号。当然,单引号是最保险的。

       至于shell呼叫的工具中,哪些支持正则表达式,可以查看下面的表2.1

 

    问3:Bash Shell和它的工具(或称命令)之间又有什么联系和区别呢?

      这个可以参考:点击打开链接 中的第一条:shell和命令之间有什么区别。

 

2  各环境对正则表达式的支持

    由于正则表达式的处理对象是字符串,即文本。其主要体现在于对文本的:验证、查找、替换。在Linux系统中,程序设计语言Java、Perl和Python等;shell工具sed、awk、grep等;数据库MySQL、PostgreSQL等都采用了正则表达式。

    另一方面,虽然正则表达式最开始是从UNIX系统中的某些工具开始使用,并逐渐流行开来的。但是现在正则表达式的使用范围比你想象的要广泛,很多windows下的编程软件都开始支持正则表达式,并且日常操作中,比如Notepad++、WPS、Word中的文本搜索,百度、Google中的搜索也都会用到正则表达式。

    针对shell脚本而言,熟练使用正则表达式,对于掌握LInux三剑客:grep、sed、awk和Linux下强大的文本编辑器:vi而言,是非常有用的。

表2.1  shell中编辑工具对正则表达式的支持
工具基本正则表达式扩展正则表达式
grep
egrep
vi
sed
awk


表2.2  各环境对正则表达式详细支持情况
命令或 环境.[  ]^$\ (  \)\{ \}?+|( )
vi ✔  ✔  ✔  ✔  ✔      
awk ✔  ✔  ✔  ✔    ✔  ✔  ✔  ✔ 
sed ✔  ✔  ✔  ✔  ✔  ✔     
ex ✔  ✔  ✔  ✔  ✔  ✔     
grep ✔  ✔  ✔  ✔  ✔  ✔     
egrep ✔  ✔ ✔  ✔  ✔   ✔  ✔  ✔  ✔ 
fgrep ✔  ✔  ✔  ✔  ✔      
perl ✔ ✔ ✔ ✔ ✔  ✔ ✔ ✔ ✔
Visual   C++ ✔  ✔  ✔  ✔  ✔      
Tcl       解释器 ✔  ✔  ✔  ✔  ✔   ✔  ✔  ✔  ✔ 

        该表来自《UNIX技术手册》(第4版)—Arnold Robbins著  O'Reilly Taiwan公司 译  东南大学出版社


3  正则表达式相关说明

    在UNIX/Linux系统中由POSIX标准来提供对正则表达式的支持。

      POSIX标准将正则表达式分为两类:

            1、基本的正则表达式

            2、扩展的正则表达式。

    而大部分Linux应用和工具仅支持基本的正则表达式。

 

    问1:什么是POSIX标准?

      POSIX标准是为UNIX和类UNIX系统,如Linux制定的一套可移植操作系统接口。所有新发布的UNIX/Linux系统,要按照该标准来设计自己新的/改进的系统。

 

    问2:为什么要制定这套标准

    由于最开始UNIX系统的发展,出现了各大厂商发布的UNIX上的代码不兼容的情况。为了增强源码在各UNIX/Linux系统上的可移植性,由IEEE制定了该标准。该标准的目的就是为了提升应用程序在各种UNIX系统环境之间的可移植性,以实现UNIX/Linux操作系统的标准化。

       由于有利于厂商的利益,厂商按照这种标准来制定系统也更容易被人们接受,所以各大厂商也纷纷采用这种标准。

    以上对POSIX标准的说明,主要参考:

    [1]  W.Richard Stevens,Stephen A.Rago. UNIX环境高级编程[M].戚正伟,张亚英,尤晋元译.第3版.北京:人民邮电出版社,2014.20~22

 

    问3:正则表达式规范

    虽然其他的组织,如windows,或语言,如PHP、Perl,有自己对正则表达式的支持和相应扩展,但是在UNIX/Linux的工具中基本就是POSIX标准制定了的对正则表达式的支持。

      不同标准对正则表达式的支持可能存在差异,但大体相同。

 

4  POSIX标准下的正则表达式及其扩展

4.1  基本正则表达式

                                                               表4.1 基本的正则表达式元字符集合及其含义

编号

符号

意义

1

*

0个或多个在*字符之前出现的那个字符

2

.

匹配任意字符

3

^

匹配行首,或后面字符的非

4

$

匹配行尾

5

[ ]

匹配字符集合

6

\

转义符,屏蔽一个元字符的特殊意义

7

\< \>

精确匹配行号

8

\{n\}

匹配前面字符出现n次

9

\{n,\}

匹配前面字符至少出现n次

10

\{n,m\}

匹配前面字符出现n~m次

 

    下面对这10种正则表达式元字符一一举例说明:

 

        ⑴、“*”符号

       含义:在*之前出现的一个字符,可以出现0次或多次

       如:grep --color -n 'hel*o'  filename

       则元字符*,限定的是字符l,重复零次或任意多次,如heo、helo、hello、helllo…… 

            (注意对heo的匹配,因为符号“*”限定可以出现0次)

           要注意一下下面这两个的区别:

           [a-z]*:匹配的是任意字符 ,[a-z][a-z]*:匹配的是以任意小写字母开头的字符   

 

        ⑵、“.”符号

        含义:匹配任意一个字符

 

        ⑶、“^”符号

        含义:匹配行首,或者是后面字符的非

        释义:

        ① 匹配行首

     一个句子有行首、行中、行尾。加了^符号,则只对首行进行字符串匹配。

     对比举例:“..cloud”表示匹配前面两个字符是任意字符,后面是cloud的字符。但是这样检索,检索的是整个文本,每行的每个字符(包含行首、行中和行尾)。

     加“^”后进行限定:“^..cloud”,则仅会在文本的各行行首进行检索要匹配的字符,而不是整个文本的内容了。

        ② 后面字符的非

     当表示后面字符的非,这种含义时,是和编号5,符号“[]”这种元字符结合使用的时候才显现这种含义。

 

         ⑷、“$”符号

         含义:匹配行尾

      这个就不解释了,和编号3、符号“^”是相同的解释。区别就是一个行首,一个行尾;一个在前,一个在后。

      用法举例:chenhaojie$

      和匹配行首的:^chenhaojie,一个在头,一个在尾。

          常用用法:

            ① 匹配空行:^$

            ② 匹配只有一个字符的行:^.$

 

          ⑸、“[ ]”符号

      含义:匹配[ ]符号中列举的任意一个字符

      用法:[ ]符号用有三种书写字符合集的方式:

          ① 穷举

          ② -    :范围

          ③ ^    :取反

      举例:[a-z]:匹配所有小写字母中的任意一个

                  [a-zA-Z]:匹配任意一个英文字母

                  [a-zA-Z][a-zA-Z]*:匹配任意英文单词

      解释:为什么[a-zA-Z][a-zA-Z]* 匹配的是任意一个英文单词

       “*”表示匹配前面字符零次或多次。而这里“*”前面的字符不是一个字符,而是一个字符集。相当于就是对这个字符集中的任意一个进行零次或多次匹配。

 

          ⑹、“\”符号

         含义:屏蔽一个元字符的特殊意义

      比如:\.  屏蔽“.”符号的任意匹配

 

         ⑺、“\<\>”符号

         含义:精确匹配

         啥叫精确匹配字符串。

      比如:\<the\>

      匹配到的就是单词the,而不是The,或者包含the的they……等等。

 

          ⑻、“\{n\}”、“\{n,\}”、“\{n,m\}”

      这三种都是“\{\}”系列,和前面编号1的符号“*”很类似。

       含义:

            \{n\}:在该式前面出现的那个字符,出现n-1次

            \{n,\}:在该式前面出现的那个字符,再次出现至少n-1次

            \{n,m\}:在该式前面出现的那个字符,再次出现n-1~m-1次

       举例:

           chen\{3\}hj:就是要匹配chennnhj

       和“*”一样,该式可以和编号5的符号“[]”组合得到一些强大的用法:

       比如:[a-z]\{5\}

           表示匹配五个连续的小写字母。


4.2  扩展的正则表达式

先给出扩展正则表达式的表格:

                                                                        表4.2  扩展的正则表达式元字符

编号

符号

含义

1

匹配0个或1个在?之前出现的字符

2

+

匹配1个或多个在+之前出现的字符

3

( )

表示一个字符集合

4

|

表示或,用以表示一组可选的字符

5

{n}
{n,}
{n,m}

和基本正则表达式编号为8、9、10的符号一样。
只是,在扩展的正则表达式下,要用这种形式,比如:
awk、 grep -E、 sed -r、 Perl

         首先说明:扩展的正则表达式,并不是所有支持基本正则表达式的工具都可以用。用之前可以查看一下表2.1。

         详细说明:

         1、“?”符号

       含义:至多匹配1个“?”前面出现的那个字符。即,匹配出现在?符号前面的那个字符,0次或1次

       举例:JO?B

       匹配到的字符串:JOB、JOOB (就两个)

 

        2、“+”符号

       和基本正则表达式编号1的“*”符号很像。它们唯一的区别就是:“*”符号可以匹配0次,而“+”符号至少匹配一次。

       如:grep --color -n 'JO+B'  filename    与     grep --color -n 'JO*B'  filename

       由于“+”至少要匹配一次出现在“+”前面的那个字符,所以O至少要匹配一次,从JOOB开始。

       这两条命令的区别就是对 JB 与 JOB的匹配,“+”匹配不出JB和JOB。而“*”可以匹配到JB和JOB.

 

        3、“( )”符号

      字符集合。这就和基本正则表达式中编号5的“[ ]”符号很像。

      而事实上,“( )”大多数情况下也确实是被“[ ]”所替代,很少被使用。

      至于“( )”的用法,很多时候和符号4的“|”结合使用:

      比如:(a|b|c)

          或者:gawk  '/^(no | so)/'  file

          表示匹配文件file中,以模式no或so开头的行

 

4.3  POSIX正则表达式字符集

     1  首先,给出所有POSIX字符集,

                                                                表4.3  POSIX正则表达式字符集

编号

字符集

含义

编号

字符集

含义

1

[:alpha:]

字母字符

7

[:graph:]

非空格字符

2

[:alnum:]

字母与数字字符

8

[:print:]

任何可以显示的字符

3

[:cntrl:]

控制字符

9

[:space:]

任何产生空白的字符

4

[:digit:]

数字字符

10

[:blank:]

空格与Tab键

5

[:xdigit:]

十六进制数字字符

11

[:lower:]

小写字符

6

[:punct:]

标点符号

12

[:upper:]

大写字符

 

2  使用说明

        ① POSIX字符集可以通过方括号“[ ]”来引用。以编号1的字符集来说明,对它进行引用后,即为:[[:alpha:]]。

        ② POSIX字符集属于POSIX标准下的基本正则表达式,可以在表2.1中给出的能够使用基本正则表达式的几个工具中使用。

 

3  说明:

      从上面的“使用说明”第一条可以知道,POSIX字符集是通过方括号引用的。方括号[ ]是用于字符的集合,但是匹配的是单个字符。

         POSIX字符集,相当于是把原本放在方括号“[]”中的具有一类特征的字符做了集合,省去了手动输入的麻烦。

 

4  使用举例:

      ① 比如,替换文本中所有以小写字母组成的字符串,用数字1替换

      命令:sed -n “s/[[:lower:]][[:lower:]]*/1/p” file

      说明:其中的[[:lower:]][[:lower:]]*,和[a-z][a-z]*的含义是完全相等的。均表示以连续的小写字母组成的字符串。

 

        ② 再比如,查找文本中所有以字母组成的字符串。

      命令:grep --color “[[:alpha:]][[:alpha:]]*” file

      说明:这里的[[:alpha:]][[:alpha:]]* 与 [a-zA-Z][a-zA-Z]*含义是一样的。



               ——以上内容基于《Linux运维之道》 丁明一 编著 


参考:

[1] gexiaobaohelloworld.  Linux-正则表达式.  https://blog.csdn.net/gexiaobaohelloworld/article/details/9147365#t0, 2018-5-30

[2] renwotao2009.  Linux中的正则表达式.  https://blog.csdn.net/renwotao2009/article/details/50937038, 2018-5-30

[3] hjlin. linux中awk,sed,grep等命令使用区别. http://blog.chinaunix.net/uid-9078996-id-2010308.html,2018-6-17

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值