Fung's DBA World

DBA knowledge,standing on the shoulders of giants.

[Shell学习笔记]正则表达式与grep

September 24, 2013

1.正则表达式元字符

1
2
3
[root@linora shell]# cat lettle 
Hi,Tom 
Tommy tomrrow! 
需要将以上文本的Tom改为David,需注意到,其他单词也含有tom或者Tom字样。Vi命令模式中使用%s/[Tt]om/David/g显然是不行的,它会将其他单词中含有tom字样的全部取代为David。

正解:

正则表达式%/s/\<[Tt]om\>/David/g达成此目的或者:1,$s/\<[Tt]om\>/David/g

:1,$s/\<[Tt]om\>/David/g

这条vi命令的意思是,从文件的第一行到末尾,用David替换单词Tom或者tom。正则表达式元字符\<和\>表示单词的开始和结束(vi跟grep支持)。表1-1列出了可以在所有版本的vi、ex、grep、egrep、sed和awk中使用的正则表达式元字符。

1-1 正则表达式元字符

元字符 功能 示例 匹配对象
^ 行首定位符 /^love/ 匹配所有以love开头的行
$ 行尾定位符 /love$/ 匹配所有以love结尾的行
. 匹配单个字符 /l..e/ 匹配包含一个l,后面跟两个字符,再跟一个e的行
* 匹配0或者多个重复的位于*前的字符 /*love/ 匹配包含跟在0个或者多个字符后的love的行
[] 匹配一组字符中的任意一个 /[Ll]ove/ 匹配Love或者love
[x-y] 匹配指定范围内的一个字符 /[A-Z]ove/ 匹配后面跟着ove的一个A至Z的任意字符
[^] 匹配不在指定组内的字符 /[^A-Z]/ 匹配不在范围A至Z之间的任意一个字符
\ 转义字符 /love\./ 匹配包含love,后面跟一个句号

1.1.正则表达式范例

I had a lovely time on our little picnic.
Lovers were all around us. It is springtime. Oh
love, how much I adore you. Do you know
the extent of my love? Oh, by the way, I think
I lost my gloves somewhere out in that field of
clover. Did you see them?  I can only hope love
is forever. I live for you. It's hard to get back in the
groove.
说明:
1
/love/ 
解析:正则表达式为love,查找到的love可能是单个单词,也有可能是lovely,gloves或者clover。 注:为了减少篇幅冗余,以上文本省略,只挑出vi命令行查找命令。
1
/^love/ 
^为行首定义符,在上述短文中,vi只查找以love四个字符开头的行,前面不能有任何字符,包括空格。
1
/love$/ 
$为行尾定义符,只查找以love结尾的行,且love后面跟着换行符。 /l.ve/ 单个字符匹配,查找结果为love和live的组合。
1
/[Ll]ove/ 
方括号匹配某组字符中的一个,即vi查找包含一个L或者l后面跟着ove的正则表达式。
1
/ove[a-z]/ 
方括号内的连字符表示匹配某个范围内的一个字符,即vi查找包含ove,后面接着a-z的任意一个ASCII码字符。
1
/ove[^a-zA-Z0-9]/ 

方括号内的^为否定,即上述查找表示vi查找ove开头,但后面不是接着A-Z、a-z及0-9之间的ASCII字符,如,vi可能找到ove后面接着句号,感叹号等的字符。

1.2.复合正则表达式元字符

   ---------------------------------------------------------------
1  |Christian Scott lives here and will put on a Christmas party.|
2  |There are around 30 to 35 people invited.                    |
3  |They are:                                                    |
4  |                                                          Tom|
5  |Dan                                                          |
6  |   Rhonda Savage                                             |
7  |Nicky and Kimberly.                                          |
8  |Steve, Suzanne, Ginger and Larry.                            |
   ---------------------------------------------------------------
说明:
1
/^[A-Z]..$/ 
查找文本中所有以大写字母开头,后跟两个任意字符,再跟一个换行符的行,查找结果是第五行的Dan。
1
/^[A-Z][a-z ]*3[0-5]/ 
查找所有以大写字母开头,后面跟0个或者多个小写字母或空格,再跟数字3和一个0~5之间的数字的行。查找结果是第二行。
1
/[a-z]* \./ 
查找包含跟在0个或多个小写字母后的句点的行。结果是第1、2、7、8行。
1
/^ *[A-Z][a-z][a-z]$/ 
查找0个或者多个空格开头,后跟一个大写字母、两个小写字母跟换行符的行。结果是第四行及第五行。
1
/^[A-Za-z]*[^,][A-Za-z]*$/ 
查找以0个或者多个大小写字母开头,后面跟一个非逗号的字符,再跟0个或者多个大小写字母和一个换行符的行。结果是第五行。

1.3.其他正则表达式元字符

Unusual occurrences happened at the fair.
Patty won fourth place in the 50 yard dash square and fair.
Occurrences like this are rare.
The winning ticket is 55222.
The ticket I got is 54333 and Dee got 55544.
Guy fell down while running around the south bend in his last event.
说明:
1
/\<fourth\>/  
查找出每一行的单词fourth。\<是词首定位符,\>是词尾定位符。
1
/\<f.*th\>/ 
查找以f开头、后跟0个或者多个任意字符,再跟以th结尾的字符穿的任意单词。
1
:1,$s/\([Oo]ccur\)ence/\1rence 
上面取代例子采用\(和\)记录模式,编辑器查找完整的字符串[Oo]ccurence。如果找到了,就把圆括号中的这部分模式加上标签(即将occur或者Occur标记)。这是第一个被标记的地方(最多可标记9个),因此被称为标签1.这个模式被保存在标记为1的内存寄存器中。执行替换时候,将\1替换为寄存器的内容,然后加上单词的剩余部分rence。这样,开始时的occurence被替换为occurrence。
1
:s/\(square\) and \(fair\)/\2 and \1 
编辑器查找正则表达式square and fair,将square标记为标签1,fair标记为标签2。执行替换时候,\1被寄存器1的内容替换,\2被寄存器2的内容替换,最后结果为fair and square。
1
/5\{2\}2\{3\}\./ 
模式的重复\{n\},表示查找含有两个数字5,后面接三个数字2,最后接一个句点的行。

2.grep

grep表示全局查找正则表达式并且打印结果行(global search regular expression and print out the line)。 使用grep的好处在于,不需要启动编辑器就可以执行查找操作,也不用把正则表达式括在正斜杠里。使用grep比vi快得多。       grep命令在一个或者多个文件中查找某个字符模式,如果这个模式中包含空格,就必须用引号把它括起来。 命令格式
grep oracle /etc/passwd
      如果发现了要查找的模式,grep返回的退出状态为0,如果没找到,返回的退出状态为1,如果找不到指定文件,退出状态是2.

2.1.  grep中的元字符

2-1 grep使用的正则表达式元字符

元字符 功能 示例 匹配对象
^ 行首定位符 '^love' 匹配所有以love开头的行
$ 行尾定位符 'love$' 匹配所有以love结尾的行
. 匹配单个字符 'l..e' 匹配包含一个l,后面跟两个字符,再跟一个e的行
* 匹配0或者多个重复的位于*前的字符 '*love' 匹配包含跟在0个或者多个字符后的love的行
[] 匹配一组字符中的任意一个 '[Ll]ove' 匹配Love或者love
[^] 匹配不在指定组内的字符 '[^A-Z]' 匹配不在范围A至Z之间的任意一个字符
\< 词首定位符 '\<love' 匹配包含以love开头的词的行
\< 词尾定位符 'love/>' 匹配包含以love结尾的词的行
\(..\) 标记匹配到的字符 '\(love\)ing' 模式love被保存在1号寄存器中,之后可用\1引用它
x\{m\}或x\{m,\}或x\{m,n\} 字符x的重复次数:m次、至少m次、至少m次但不超过n次 'o\{5\}','o\{5,\}'

,'o\{5,10\}'
匹配连续出现5个o、至少5个o或者5~10个o的行

2-2 grep的选项

选项 功能
-b 在每一行前面加上其所在的块号,根据上下文定位磁盘时可能会用到
-c 只显示匹配到的行的数目,而不显示行的内容
-h 不显示文件名
-i 忽略大小写
-l 只列出匹配行所在文件的文件名,文件名之间用换行符分隔
-n 在每一行前面加上它所在文件中的相对行号
-s Silent mode,即只显示报错信息,以检查退出状态
-v 反向查找,只显示不匹配的行
-w 把表达式作为单词查找,就好像他被\<和\>所包含一样

2.2.grep的退出状态

grep在shell脚本中很有用,它总会返回一个退出状态,但是sed及awk是不使用退出状态来说明查找模式是否成功的。例如:
1
2
3
4
5
6
[root@linora shell]# grep -s oracle /etc/passwdddsf 
[root@linora shell]# echo $? 
2
[root@linora shell]# grep fung /etc/passwd 
[root@linora shell]# echo $? 
1
对于在bash及ksh中的变量“?”的值都是上一条命令执行后的退出状态。

2.3.grep与pipe

1
2
3
4
5
6
7
8
[root@linora shell]# ls -l 
total 12 
drwxr-xr-x 2 root root 4096 Sep 24 01:22 dir1 
drwxr-xr-x 2 root root 4096 Sep 24 01:22 dir2 
-rw-r--r-- 1 root root   23 Sep 23 18:44 lettle 
[root@linora shell]# ls -l |grep '^d' 
drwxr-xr-x 2 root root 4096 Sep 24 01:22 dir1 
drwxr-xr-x 2 root root 4096 Sep 24 01:22 dir2 
说明: ls命令的输出通过pipe传给grep。输出结果中以字母d开头的所有行都被打印出来,及上述命令打印当前目录下所有子目录。

3.egrep

egrep的好处是它在grep提供的正则表达式元字符集的基础上增加了很多元字符,但是egrep不允许\{\}和\(\)。同时egrep参数跟grep参数用法相同。

3-1     egrep使用的正则表达式元字符

元字符 功能 示例 匹配对象
^ 行首定位符 '^love' 匹配所有以love开头的行
$ 行尾定位符 'love$' 匹配所有以love结尾的行
. 匹配单个字符 'l..e' 匹配包含一个l,后面跟两个字符,再跟一个e的行
* 匹配0或者多个重复的位于*前的字符 '*love' 匹配包含跟在0个或者多个字符后的love的行
[] 匹配一组字符中的任意一个 '[Ll]ove' 匹配Love或者love
[^] 匹配不在指定组内的字符 '[^A-Z]' 匹配不在范围A至Z之间的任意一个字符
+ 匹配一个或者多个加号前的字符 '[a-z]+ove' 匹配一个或者多个小写字母后面跟ove的字符
? 匹配零个或者一个前导字符 'lo?ve' 匹配l后跟一个或者零个字母o及vd的字符,即love或者lve
a|b 匹配a或者b 'love|hate' 匹配love或hate
() 字符组 'love(able|ly)(ov)+' 匹配lovable或lovely,匹配ov的一次或者多次出现

3-2     egrep用法示例

命令 命令执行的操作
egrep '^ +' file 打印一个或者多个空格开头的行
egrep '^ *' file 打印零个或者多个空格开头的行
egrep '(Tom|Dan) Savage' file 打印Tom Savage或Dan Savage的行
egrep '(ab)+' file 打印一个或者多个ab的行
egrep '^X[0-9]?' file 打印X开头,后面接零个或者一个数字的行
egrep 'fun\.$' file 打印fun.结尾的行
egrep '[A-Z]+' file 打印包含一个或者多个大写字母的行
egrep '[0-9]' file 打印包含数字的行
egrep '[A-Z]...[0-9]' file 打印大写字母后面跟着三个任意字符最后再跟数字的行,共计五个字符
egrep '[tT]est' file 打印包含test或Test的行
egrep '(Susan|Jean) Doe' file 打印包含Susan Doe或Jean Doe的行

EOF

Permalink: http://www.oraclema.com/linux/grep-and-regular-expression.html