一、什么是grep和egrep

   首先解释下为什么叫grep,他从理解和发展来看应该拆解为gp和re。

   据《UNIX编程艺术》此书上的记载,在UNIX早期文本编辑器ed提供一种操作:g/字符/p ,g代表global,p代表print,很显然这个功能的意思大概是在文本中全局寻找到有这个特定字符的行,然后显示给我们看。

   RE就是regular expression,也就是正则表达式。一个做字符串匹配的强大的工具。

   所以grep大概就是g/re/p这个意思,也是这么来的。大家也都知道,正则表达式分为基本正则表达式和扩展(extend)正则表达式。这样一来就有了所谓的grep和egrep,其实应该叫grep和gerep,为保持名字的一致,就是现在的样子。

   这样很容易明白,grep即--全局寻找-基本则表达式匹配到的内容所在行-并打印出来,egrep即--全局寻找-扩展正则表达式匹配到的内容所在行-并打印出来。

二、命令格式及怎么使用

   命令使用格式:grep [option] "pattern" file,...

   根据一的理解我们知道,pattern既可以是特定的单词也可以是正则表达式。

   egrep与以上格式一致,我们也可使用grep -E  [option] "pattern" file,...来使用正则表达式。

   使用方法:

   常用选项[option]:

       -v:取反,显示被模式匹配之外的所有行,即不能被模式所匹配到的行:

       -o:仅匹配被模式匹配到的字串,而非整行

       -c : 显示匹配到行的数目,而不显示行的内容

       -h : 不显示文件名

       -l : 只列出匹配行所在文件的文件名

       -n : 在每一行的前面加上它在文件中相对的行号

       -i :不区分字符大小写,ignore-case

       -E:支持扩展的正则表达式

       -A#:after,匹配到的行以及下面#行

       -B#:before,匹配到的行以及上面#行

       -C#:上下文,匹配到的行以及上下面个#行

三、正则表达式匹配

   正则表达式的匹配依循尽可能多的匹配的方式,即一行可以多次匹配,连续显示,可称之为贪婪模式

   正则表达式匹配大致可分为:字符匹配次数匹配字符位置锚定单词位置锚定分组引用

   1.字符匹配

grepegrep
.    : 表示匹任意单个字符同左

[ ]  :表示匹配括号内的任意一个字符

特殊模式:[0-9]、[a-z]、[A-Z],分别表示数字,小写字母,大写字母

同左
[^]  :表示匹配括号内以外的任意一个字符同左

   1.1 POSIX字符类

  为了在不同国家的字符编码中保持一至,POSIX(The Portable Operating System Interface)增加了特殊的字符类,如[:alnum:]是A-Za-z0-9的另一个写法。要把它们放到[]号内才能成为正则表达式,如[A- Za-z0-9]或[[:alnum:]]。在linux下的grep除fgrep外,都支持POSIX的字符类。

    POSIX字符在使用上依然要在[]中,如[[:alpha:]]才能正确使用

[:alpha:]           字母
[:digit:]           数字
[:alnum;]           字母和数字
[:upper:]           大写字母
[:lower:]           小写字母

[:space:]           所有空白字符(新行,空格,制表符)

[:graph:]           非空字符(非空格、控制字符)
[:print:]           非空字符(包括空格)
[:punct:]           标点符号
[:cntrl:]           控制字符

[:xdigit:]         十六进制数字(0-9,a-f,A-F)

    2.次数匹配,指定匹配其前面的字符次数

grepegrep
*    :匹配其前面的字符,任意次同左
\?   : 匹配其前面的字符,0或1次?   :  同左

+   :  匹配其前面的字符,至少1次
\{m\} :匹配其前面的字符,m次{m} :  同左
\{m,n\} :匹配其前面的字符,m到n次{m,n}: 同左
\{m,\}  :匹配其前面的字符,至少m次{m,} : 同左
\{,n\}  :匹配其前面的字符,至多n次{0,m}: 同左

   3.字符的位置锚定

grepegrep
^  : 锚定行首同左
$  : 锚定行尾同左

   4.单词的位置锚定(注:单词为被符号或空格分隔的连续的字母和数字,非英语单词)

grepegrep
\<char 或  \bchar  : 锚定词首,char为单词同左
char\> 或  char\b  : 锚定词尾,char为单词同左

   5.分组

grepegrep
\(\)  : 将括号内当一个整体匹配
()   :同左

left|right : 或,匹配left或right

conC|cat     conC或者cat

con(C|c)at   conCat或者concat   括号中的分组依然可引用

   6.引用(分组存在才能引用,按分组顺序可引用多个分组,引用的是正则表达式所匹配到的内容,而不引用正则表达式模式去匹配)

grepegrep

\num : 引用第num个左括号所在的分组的内容

\num : 同左


四、记录一个让我思考过的问题

问题:使用ifconfig显示网络参数,并用grep匹配1-255的整数。

    解:如何匹配?可以使用分类法,

       匹配1位数:1-9,[1-9],匹配2位数10-99,[1-9][0-9]

       匹配3位数,又可分为100-199,1[0-9]\{2\}

                          200-249,2[0-4][0-9]

                          250-255,25[0-5]

       于是可以得到一个扩展正则表达式:[1-9]|[1-9][0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5]

       尝试去匹配。

grep和egrep的使用_RE

   失败,为什么这样。数字和字母相邻,这样不符合要求,数字需要单独存在,故要加单词锚定。而且这样一来数字左右也只能是符号,也把大于255的数字排除了。

grep和egrep的使用_grep_02

   又失败。但是,加了单词锚定符,数字的旁边为什么会有字母,锚定符里面只有数字,即时不能精确匹配到1-255,也不可能左边或右边还有字母啊。需要加分组吗?

grep和egrep的使用_RE_03

   分组时对的,可是为什么,只是尝试而已,为什么就可以。而且不仅让数字与字母分开,数字匹配范围也缩小到了1-255。

     什么原因。第二个与第三个以及第一个相比,连续的数字为什么会少匹配一个,这是什么原因。仔细分析第二个中间的大数字,为什么锚定了,却空余,它的工作机制是怎样的。3071549匹配307154,37434匹配3743。它们都是两位两位的符合我们的匹配,而且各位没有匹配,个位也在范围内,而且锚定符为什么没有用。

     仔细分析这一串:\b[1-9]|[1-9][0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5]\b

     没有锚定到说明这个串里面有两位匹配时不被锚定的。\b[1-9]|[1-9][0-9]|1[1-9]{2}|2[0-4][0-9]|25[0-5]\b,为什么不被锚定。仔细观察,原来词首锚定只锚定了[0-9],所有无法匹配词尾的个位数,而词尾也只锚定了25[0-5]。

   这一正则式的范围是这样:\b[1-9][1-9][0-9]1[1-9]{2}2[0-4][0-9]25[0-5]\b。故加上分组时对的。

写在最后:

使用grep的好处在于,不需启动编辑器就可以执行查找操作。

但是如果pattern中包括空格,则必须被\引用。

输出结果到屏幕,对文件不产生影响。grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作