很多时候我们都有文本检索的需要,比如我们使用windows的时候,经常会在某个doc或txt文档中搜索自己想要的内容。而在使用linux的过程中,我们同样会遇到文本检索的场景。
在linux环境下,我们使用grep,egrep及fgrep,来实现文本检索的功能。由于grep,egrep支持使用正则表达式来表示匹配模式,使得linux环境下的文本检索功能变得非常强大。下面我们就来详细描述下何为grep,以及使用正则表达式配合grep实现文本检索的方法。
一,什么事正则表达式?
很难用比较通俗的语言来描述,暂且复制各种百科里的内容过来。
如百科所说,“正则表达式使用单个字符串来描述一系列某个句法规则的字符串”,其中“单个字符串”是掌握正则表达式的关键和难点,这个内容会在第三部分中以grep为例来详细描述。
二,grep及其使用方法。
grep [OPTIONS] PATTERN[FILE...]
这是帮助文档中给出的信息,其中“PATTERN”即指上文所说的”单个字符串”,是比较难以掌握的部分,也是grep能够完成复杂搜索任务的关键因素,当然“PATTERN”也可以是简单的字符串。这部分我们仅使用简单字符串,重点介绍grep的基本用法及一些常用的“OPTIONS”。
举例1:在/etc/passwd文件中搜索包含有“root”字符串的行。
grep “root” /etc/passwd
这个就是grep最简单的用法,/etc/passwd文件中包含“root”字符串的行被打印至屏幕。此外,grep还给定了一些选项,使得我们在搜索时更为快捷。
--color:表示给搜索到的字符串添加颜色,很好用的一个功能,也比较简单,在此不做过多说明。以下的例子中我们已定义alias grep=”grep –color”。
-o:表示仅显示匹配到的内容,例一加上-o选项则会看到如下结果:
grep -o “root” /etc/passwd
-i:表示不区分大小写。
例2,在/tmp/test/目录下编写包含有ROOT,ROOt,root的文件greptest,执行
grep -i "root" /tmp/test/greptest
看到如下结果:
-v:表示不能被模式匹配到的行
三,使用正则表达式配合grep完成搜索任务。
由于grep支持使用正则表达式来表示“PATTERN”,使得其功能变得异常强大,下面我们就来介绍一下正则表达式配合grep搜索的一些常用方法。
正则表达式由元字符及正常字符组成,其中的元字符不表示字符本身的意义,而是用于表达控制或通配等功能;元字符是书写和理解正则表达式的关键,下面就来说说一些常见的元字符。
1,表示字符匹配的元字符
.:点号表示匹配任意单个字符,例如在/etc/passwd文件中搜索r后跟两个任意字符,然后是t的行,就可以用grep "r..t" /etc/passwd
[]:表示匹配指定范围内的任意单个字符。
[^]:表示指定范围外的任意单个字符。
在正则表达式中匹配指定范围的字符集合有以下常用表达:
[0-9]表示匹配任意单个数字,与[[:digit:]]相同。
[a-z]表示匹配任意单个小写字母。
[A-Z]表示匹配任意单个大写字母。
[a-zA-Z]:表示匹配任意单个字母,同[[:alpha:]]。
[[:punct:]]表示匹配任意标点符号。
[[:space:]]表示匹配空白字符,包括空格和制表符。
[0-9a-zA-Z]表示匹配所有的字母和数字,同[[:alnum:]]。
举例:在/etc/rc.d/rc.sysinit文件中搜索出现了n或N,且其后是非字母的行,就可以使用grep "[nN][^[:alpha:]]" /etc/rc.d/rc.sysinit来表示
在此,给出一个我在学习中犯的一个错误:搜索/etc/rc.d/rc.sysinit中出现了no或No的行。这道题的答案应该是grep “[nN]o“ /etc/rc.d/rc.sysinit而不是 grep –i no/etc/rc.d/rc.sysinit,
因为后一个命令匹配到的是no,No,NO这三种结果。
2,表示次数匹配的元字符
*:表示匹配其前面字符任意次。
\?:表示匹配其左侧字符0次或1次。
\+:表示匹配其左侧字符1次或多次。
\{m\}:表示精确匹配其左侧字符m次。
\{m,n\}:表示其左侧字符出现的次数在m和n之间才能被模式匹配到。
\{m,\}:表示其左侧字符至少出现m次才能被搜索到。
举例:
1)找出/etc/passwd中o连续出现两次的行
2)找出grep.test中a之后b出现了一次或两次的行。
3,位置限定。
使用正则表达式,除了能表达字符的种类和次数以外,还能指定字符出现的位置,下面介绍下,常用的锚定位置的表示方法。
^:表示锚定行首
$:表示锚定行尾。
\< :锚定词首,也可用\b
\> :锚定词尾,也可以用\b
举例:找出/etc/passwd文件中包含fedora的行
4,分组引用\(\)
分组中的模式,在某次的具体匹配过程中所匹配到的字符,可以被grep记忆(保存于内置的变量中,这些变量是\1, \2, ...),因此,还可以被引用;
\1: 引用,模式中自左而右,由第一个左括号以及与之对应的右括号中的模式所匹配到的内容;
\2: 引用,模式中自左右,由第二个左括号以及与之对应的右括号中的模式所匹配到的内容
比如:\(ab\(cd\)mn\)\1 \2,\1表示abcdmn,而\2表示cd。
举例:找出/etc/passwd文件中以passwd开头且以passwd结尾的文件