标签: ShellScript

1 What is Regular Expression

正则表达式(Regular Expression)是通过一些特殊字符的排列,用以查找、替换、删除 一行或多行文字字符串,是用来描述某些字符串匹配规则的工具。简单的说,就是处理字符串的方法。

1.1 为什么使用正则表达式

在进行程序设计的过程中,用户会不可避免地遇到处理某些文本的情况。有的时候还需要查找符合某些比较复杂 规则的字符串。对于这些情况,如果单独依靠程序设计语言本身,则往往会使得用户通过复杂的代码来实现,但是 如果通过正则表达式,则会以非常简短的代码来完成。

目前,正则表达式在UNIX或者Linux中得到了广泛的应用。常见的支持正则表达式的UNIX工具如下:

  • grep命令族: 用于匹配文本行。
  • sed流编辑器: 用于改变输入流。
  • awk: 用于处理字符串的语言。
  • more或者less等: 文件查看程序。
  • ed、vi或者vim等: 文本编辑器。

1.2 如何学习正则表达式

学习正则表达式的最好的方法就从学习和理解最简单的例子开始。在学习正则表达式时,需要注意以下几点。 1.重点在于理解元字符 在正则表达式里面,处于核心地位的就是元字符。正则表达式所描述的规则最终都是由元字符表达出来。因此, 对于常见的正则表达式元字符,必须完全理解和掌握其涵义,这样才能灵活的运用。 2.掌握好正则表达式的语法 正则表达式之所以简练,是因为它有严格的语法规则。。例如,元字符"*"表示匹配该符号前面的一个普通字符0次或者多次。 3.开拓思路,寻找最佳的表达方法。 对于同一个需求,可能会有许多种编写正则表达式的方法。但是,在这些方法中,总会有一种或者较少的几种方法 是最简练的,并且是最完备的。所以,要不断的思考有没有更好的解决方法。

1.3 如何实践正则表达式

当一个正则表达式完成之后,要保证这个表达式一定是准确的,就需要不断地测试,这样才可以确定其正确与否。在不同的环境下, 需要用不同的工具来帮助完成测试的过程。如果是在Shell命令行中,通常使用grep命令来测试。

2 正则表达式基础

这里主要是各种元字符及其使用方法。

2.1 正则表达式的原理

正则表达式是对文本进行过滤的工具。而正则表达式之所以拥有过滤文本的功能,是因为它定义了一系列的元字符, 通过元字符配合其它的字符来表达出一种规则,只有符合该规则的文本才能保留下来,不符合该规则的文本则被过滤掉。 所谓元字符,是指用来描述字符的字符。元字符的作用在于对字符表达式的内容、转换以及各种操作信息进行描述。而 正则表达式就是由各种元字符和一般字符构成的字符串。

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"
  • 如何精确的匹配一个文本行?
^cat$   #表示匹配以字符c开头,紧接着是一个字母a,最后以字符t结尾的文本行,除了这3个字符外,文本行中
不包括其它任何字符。
  • 几种特殊情况
^$   #匹配所有的空行,行中没有任何字符,包括空白字符。
^ 和 $ 表示匹配所有行,因为任何一个文本行都有开头和结尾。

3.单个字符匹配"." 圆点"."用来匹配任意单个字符,包括空格,但是不过括换行符"\n",但使用"."符号后,意味着该位置一定有一个字符,无论它是什么字符。

#!/bin/bash

#列出所有的包含字符串"samba"的文件名
str=`ls /etc | grep "samba"`

echo "$str"
echo "==================================="

#列出包含字符串samba以及另外一个字符的文件名
str=`ls /etc | grep "samba."`  #表示samba后面至少有一个字符

可以连续使用圆点符号来匹配多个字符,例如"l..p"匹配含有1个字母"l",然后是任意两个字符,接着是字母"p"。 4.限定符"*" 星号"*"是正则表达式中的限定符之一。限定符本身不代表任何字符,它是用来指定前面的一个字符必须重复出现多少次 才能满足匹配。星号"*"表示匹配其前导字符的任意次数,包括0次。 5.字符集匹配"[]" 方括号"[]"的功能比较特殊,它是用来指定一个字符集合的,其基本语法为:

[abc]

其中a、b和c表示任意的单个字符。只要某个字符串在方括号所在的位置上出现了方括号中的任意一个字符,就都满足 匹配规则。另外,对于连续的数字或字母,可以使用连字符"-"来表示一个范围。

#!/bin/bash

#筛选所有以字符r开头,并且紧跟着1个字符c的文本行
srt=`ls /etc | grep "^rc"`

echo "$str"

echo "==================================="

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

echo "$str"

当元字符"*"和"."位于字符集匹配符"[]"后,便变成了普通字符,只有字面意义,没有特殊意义。 6.字符集不匹配"[^]" 符号[^]表示不匹配其中列出的任意字符。语法如下:

[^abc]

2.3 扩展正则表达式

扩展正则表达式(Extended Regular Expression,ERE)支持比基本正则表达式更多的元字符, 但是扩展正则表达式对有些基本正则表达式所支持的元字符并不支持。但上面的6种支持,意义和用法都一样。下面是 一些在正则表达式中增加的元字符。

  1. 限定符 "+"

限定符"+"与限定符"*"基本相同,但是星号"*"限定前面的字符可以出现任意次,而加号"+"却限定前面的字符至少出现一次。

#!/bin/bash

#筛选以字符串"ss"开头,后面至少紧跟着一个字符"s"的文本行。
str=`ls /ect | egrep "^sss+"`
echo "$str"

扩展的正则表达式用egrep命令。 2.限定符"?" 用来限定前面的字符最多只出现一次,即前面的字符可以重复0次或者1次。

#!/bin/bash shell

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

3.竖线"|"和圆括号"()" 竖线"|"表示多个正则表达式之间"或"的关系,其语法为:

expression1|expression2|expression3|...|expressionn

圆括号"()"表示一组可选值的集合。竖线和圆括号经常在一起使用,表示一组可选值。

#!/bin/bash 

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

echo "$str"
[abc]=(a|b|c)
(Jeffrey|Jeffery)=Jeff(rey|ery)=Jeff(re|er)y

2.4 正则表达式字符集

在正则表达式中,普通字符集中的字符只表示它们的字面意义,不对其它字符产生影响。正则表达式的最简单的形式就是只由普通字符 集中的字符组成,不包括元字符。也可以使用POSIX字符集。

3 正则表达式应用

3.1 匹配单个字符

1.单个一般字符 所谓一般字符,是指除了正则表达式中已经定义的元字符之外的所有字符。当需要匹配某个一般字符时,可以直接将该字符作为表达式 或者是表达式的一部分。

str=`grep "a" filename`

2.转义后的元字符 元字符要转义之后才会变成字面的意思(普通字符)。 3.圆点表达式 4.方括号表达式

3.2 匹配多个字符

str=`grep "matter" filename` 
srt=`grep "o[ru]" filename`

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

"^[[:digit]]{3}"   #表示以任意3个数字开头
"[[:digit:]]{4}$"  #表示以4个数字结尾的文本行

3.4 运算符优先级

  • \ 转义符
  • [] 方括号表达式
  • () 分组
  • * + ? {m,} {m,n} 限定符
  • 普通字符
  • ^ $ 定位符
  • | 或运算

3.5 子表达式

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

srt=`egrep "^([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}$" filename`
#整个表达式描述的字符串以3组重复的1~3个数字后跟一个小圆点为开头,然后以1~3个数字结尾。

3.6 通配符

4 grep命令

4.1 grep命令的基本语法

grep命令的名称来自于全局搜索正则表达式并打印文本行(Global Search Regular Expression and Print out the line),基本语法如下:

grep [options] pattern [file...]

其中options表示选项。pattern表示要匹配的模式,file表示一系列的文件名。grep命令会从一个或者多个文件中搜索满足指定模式的文本行,并且打印出来。 模式后面的所有的字符串参数都被看做文件名。

常用的grep命令选项

  • -c 只打印匹配的文本行的行数,不显示匹配的内容。
  • -i 匹配时忽略字母的大小写
  • -h 当搜索多个文件时,不显示匹配文件名的前缀
  • -l 只列出含有匹配的文本行的文件的文件名,不显示具体的匹配的内容
  • -n 列出所有的匹配的文本行,并且显示行号
  • -s 不显示关于不存在或者无法读取文件的错误信息
  • -v 只显示不匹配的文本行
  • -w 匹配整个单词
  • -x 匹配整个文本行
  • -r 递归搜索,不仅搜索当前目录,还要搜索其各级子目录
  • -q 禁止输出任何匹配结果,而是以退出状态码的形式表示搜索的=是否成功,0表示匹配到了。
  • -b 打印匹配的文本行到文件头的偏移量,以字节为单位
  • -E 支持扩展正则表达式
  • -P 支持Perl正则表达式
  • -F 不支持正则表达式,将模式按字面意义匹配