这两天抽空看了一下正则表达式,随之也基本会用grep命令了。关于grep和正则表达式的具体使用,总结成文章如下。
什么是grep?
grep (Global search Regular Expression and Print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。
什么是正则表达式?
正则表达式(Regular Express)就是由一系列特殊字符组成的字符串, 其中每个特殊字符都被称为元字符, 这些元字符并不表示为它们字面上的含义,而会被解释为一些特定的含义。
正则表达式的元字符
1.句点(.)
在正则表达式中,句点(.)可以匹配任何的单个字符。比如:
e.sionte:可以是edsionte,e#sionte,e7sionte等等;
ed…te:可以是edsionte,ed@wdte等
Try:
:%s/ a.d /@/g
打开任意一个文本文件(本文中的所有命令都是使用这里的文章进行的测试),在vim命令状态下输入上述命令。这条命令的意思是:在所有行(%s代表所有行)中查找符合“ a.d “的字符串(注意a前面和d后面均有一个空格),并且将符合条件的字符串替换成@;g代表将每一行中符合上述条件的所有字符串都做相应替换,否则只会替换每一行的第一个否和条件的字符串。在上述命令中,属于正则表达式的字符串为两个/之间的部分。
2.^符号
在正则表达式中,^符号表示跟行首进行匹配。比如:
edsionte is a good boy. edsionte likes eating.edsionte likes music.
^edsionte只会跟行首的edsionte进行匹配,而不是和位于行中的其他edsionte进行匹配。
Try:
:%s/^/ /
上述命令在一个文本文件的每行都插入五个空格。对于上述命令,在命令末尾加g和不加g作用是一样的。
3.美元符号($)
与^符号相反,美元符号($)代表跟行尾进行匹配。比如:
edsionte is eating a apple.edsionte will eat that pear.This cup of milk was drunk by edsionte.
edsionte$不会与末尾的edsionte进行匹配,因为这一行最后一个字符是句点(.)。而且它更不会与此行中其他两个edsionte进行匹配。同样的,对于上述命令,在命令末尾加g和不加g作用是一样的。
那么如何匹配行尾的句点?你会想到是这样:.$。不过,这个正则表达式表示的确实匹配行尾的任意的单字符。学过C语言的你,应该知道为什么了吧?我们上面说过正则表达式是由元字符组成,因此句点在正则表达式中不会代表它本身的意思。想要使用句点本身,即得在句点前加\。也就是说,\.$才会真正的匹配行尾的句点。这其实就是转义字符,got it?
Try:
:%s/..$//
删除每行的最后两个字符。
4.[…]结构
在正则表达式中,使用[…]来匹配包含在此结构中的一个字符。比如:
[Tt]he:不管是The还是the都否和匹配要求,这条正则表达式很好的处理了出现在行首的那些单词。但必须注意的是,在字符串“Ttheapple”中,使用上述正则表达式所匹配的是the,而不是Tthe。
[0123456789]:匹配的是任意一个数字,更简单的写法是[0-9]。
[^0-9]:匹配非数字的单字符。请注意这条正则表达式和^[0-9]的差异。
一些特殊的规则是,如果要匹配一个连字符,必须将连字符放在靠近左[的位置。如果方括号内有^必须将^放在所有匹配字符的前方,比如:
[-0-9]:匹配一个数字或者连字符。
[^-0-9]:匹配一个不是连字符或数字的字符。
Try:
:%s/[Hh]arry Potter[0-9]/HARRY POTTER/g
将诸如harry potter3、Harry potter5等这样的字符串都替换成HARRY POTTER。
:%s/HARRY POTTER/*harry potter*/g
将上一步替换后的字符串都换成*harry potter*。可能你会有这样的疑问:*,.,和^等这样的字符不是元字符吗,为什么这里可以直接使用*的本来意思?这是因为元字符只有在搜索串(也就是在正则表达式中)中才会有特殊意义,在替换串中则不会有特殊意义。
5.星号(*)
在正则表达式中,用星号来匹配零到多个紧靠在星号左边的那个字符。比如:
.*:表示零到多个任意字符。因为正则表达式总是寻求最大匹配,因此.*总是匹配一整行。
go*le:可以用来匹配gle,gole,goole,gooooooooooole等。
goo*le:最小的匹配为gole。
t.*t:匹配前后均为t的字符串,而且匹配的是最大长度的字符串。
Try:
:%s/ */ /g
将每一行中的一个到多个空格都全部换成一个空格。
:%s/[a-zA-Z][a-zA-Z]*//g
这个会有什么结果,试试就知道。
6.\{…\}结构
使用\{…\}这样的结构可以匹配精确数目的字符。比如:
t\{1,5\}:匹配1到5个连续的t。
[a-zA-Z]\{4,8\}:匹配4到8个连续的字母。
[0-9]\{8\}:匹配正好8个数字。
[a-z]\{4,\}:匹配至少4个连续的小写字母。
Try:
:%s/[a-z]\{5,\}/@/g
将至少5个连续的小写字母替换成@。
grep的使用
grep命令的基本使用方法是:grep 模式 文件名。文件中符合模式的字符串所在行均会被打印出来。比如:
grep include hello.c:即在hello.c中查找包含字符串include的那些行。
如何将上述我们所熟悉的正规表达式与grep命令结合起来?模式处即为正则表达式,并用单引号包含。比如:
grep ‘[Hh]arry [Pp]otter’ harry.txt:在harry.txt中查找harry potter所在的行,其中H和P是不区分大小写的。
另外,grep命令还有下面一些选项,可以使grep命令使用的更灵活。
-i:模式匹配时忽略大小写的差异;
-l:只输出匹配模式的文件名,而不打印匹配的行;
-q:匹配成功并不将结果在标准输出中显示;
-v:显示不符合模式的行;
-n:在匹配行前显示行号;
e.sionte:可以是edsionte,e#dsionte,e7dsionte等等;
这个对着吗?
[回复一下]
edsionte 回复:
10月 18th, 2010 at 17:44
@alenChou, 那是?
[回复一下]
alenChou 回复:
10月 18th, 2010 at 17:50
@edsionte, e.sionte中的 . 只能是替换一个任意字符。那你的e#dsionte做何解?
[回复一下]
edsionte 回复:
10月 18th, 2010 at 17:58
@alenChou, 呀。。是我写错了。。我改了去。。
[回复一下]