因为在之前说过grep指令支持正则表达式,因此在次使用grep来进行学习
一、正则表达式基础
1、查找特定的字符串
为grep的基本功能,之前已经说过了,主要是通过指令grep 'strname' filename
2、使用[]来查找集合字符
[]代表的是某一个字符,而其中使用的式限定该字符的规则,其中使用[^]代表与某规则相反,如下说是^e的结果就是啥也看不到,相应的规则表达形式在后续总结。
3、行首与行尾字符^$
为了在已经筛选完成的结果中进一步筛选,如列出查找的字符在句首的行显示出来,那么可以使用^来进行筛选,与上面的[^]存在区别,为了进一步说明区别grep -n '^[^a-zA-Z]' log_complex.txt 的意思为找到不以字母开头的行,第一个^代表的就是行首,第二个[^]代表的就是取反,在[]内部和外部的^的意思是不一样的
对于查找词在句尾的时候可以使用$来进行查找,但是如下所示windows下的断行符并不仅仅隐藏$结尾,其隐藏的为^M$,但是这个^M不是字符不可进行匹配操作,不可使用查找,而在linux下为.$,在linux中.字符有特殊的意义,因此需要使用转义字符\.$
4、任意一个字符.与重复的字符*
.(小数点):代表一定有一个任意字符。
*(星号):代表重复前面的字符0到n次,为组合形态。注意这是正则表达式。
在之前讲过shell的通配符,其中:
* :匹配任意多个字符(包括零个或一个)与正则表达式存在区别
? :匹配任意一个字符(不包括零个)
例如使用grep 'g*g' text.txt查找包含以g开头和以g结尾的字符串,如下所示,实际上缺少了一个’.‘,应当的输入为grep 'g.*g' text.txt,所有问题的根源在于*正则表达式可以表示前一个字符0个元素,相当于直接消除了前面的元素。使用’.‘在’*‘之前相当于没有消除前一个字符。
5、使用连续RE字符范围
4中找出的是任意多的字符,那么需要找到限定的字符数量该如何操作?如上面的找2~5个o在gd之间。此时就需要使用范围限定字符{},由于{}在shell中有特殊意义,因此需要使用转义字符\配合使用,如在上述的结果中查找在字符gd之间包含两个以上的o的goo*d形式的行的操作为: grep -n 'go\{2,5\}'d text.txt
上下限可以不指明表示不少于和不多于,例如查找在字符gd之间包含不少于2个o的行可以使用 grep -n 'go\{2,\} text.txt'
6、总结
正则表达式的特殊字符与一般命令行输入的通配符是不一样的!
^word:待查找的字符串(word)在行首。
word$:带查找的字符串(word)在行尾。
. :一定代表一个任意字符
*:代表0~n个与前一个字符重复的字符
[list]:表示从集合集的RE字符中找到想要选取的字符
[n1-n2]:从集合集的RE字符中找到想要选取的字符范围,但是要明确语系的,不然范围的选择会出现问题
[^list]:表示从集合的RE字符中找到不要的字符串和范围。
\{start,end\}:start或者end可以省略一个,若接该内容的最后一个字符为o,则表示限定o字符出现的次数为start与end之间。
在list的选择中会由于编码语系的影响而造成一定的问题,因为有的编码是a,b,c...z但是有的却是a,A,b,B,c,C....z,Z,因此为了避免编码问题带来的集合的错选,有一些特殊的符号可以使用
[:alnum:]:0-9,A-Z,a-z
[:aipha:]:A-Z,a-z
[:blank:]:空格和键值
[:cntr:]:代表键盘上的控制按键,包括del、contrl等
[:digit:]:代表数字
[:graph:]:除了空格与tab键意外的其他所有按键
[:lower:]:a-z
[:punct:]:代表标点符号
[:upper:]:大写的A-Z
[:xdigit:]:代表16进制的数字类型,包括0-9,a-z,A-Z
[:print:]:任何可以被打印出来的字符
注意下面的错误,一定在外面另加一个[],也就是说需要[[:pattern:]],下面是查找一个包含16进制字符的以9结尾的行。
查询满足s(标点)t的行
使用print标准查找
使用上述方法查询在etc文件夹下的链接文件
7、sed工具
sed的作用可以对标准输入进行处理,包括替换删除、新增、选定特定行的功能。可以看到sed类似于filter能够对输入流进行编辑,过滤。
语法规则是:sed [-nefr] [动作]
-n :在一般的sed用法中,所有的标准输入都会被列在屏幕上,但是在该模式下,只有经过特殊处理的才会被显示
-e :直接在命令行模式上进行sed的动作编辑
-f:直接讲sed的动作写在一个文件内,-f filename 则是可以执行filename内的sed动作
-r :sed 的动作支持的是拓展型正则表达式的语法(默认式基础的正则表达式语法)
-i:直接修改读取的文件内容,而不是在屏幕输出
动作说明: n1,n2 function 代表在n1 和n2之间执行function
function:
a:增加,后面可以接字符串,这些字符会在新的一行出现。
c:替换,后面可以接字符串,这些字符串可以替换n1与n2之间的所有的行。
d:删除,通常不接任何内容。
p:打印内容
i:插入,i后面可以接字符串,这些字符串会插入当前行的上一行。
s:替换,可以进行替换工作,通常这个动作可以搭配正则表达式。
使用function d 进行删除8-9行的内容。
同样的删除10行以后的所有行,其中$代表最后一行,所有的操作并不会影响到原始文件,因为其仅仅能够处理流数据。
在某一行进行添加使用a,可以使用\进行多行的输入,一定到有空格!a是在制定行后,i为指定行前。
将2-4行替换为NO 2-4 number字符串,实际上可以看到行号都没有了,直接替换了。
打印选定的行使用function p 但是问题在于-n 安静模式,实际上不使用-n有很大的输出影响,即为选定的行会重复输出。
在进行文本的替换使用‘s/要被替换的内容/新的字符串/g’
使用组合替换删除,使用grep选出所需要操作的行,使用seed对选出的行进行删除等操作
之前的所有操作都不具备更改原始文件的能力,为了增加sed对原始文件的修改能力使用-i参数,例如 sed -i 's/test/change/g' text.txt ,关键在于使用-i需要后接文件,也不难以理解,因为你毕竟需要改动源文件。
在使用-i 进行添加a的时候会另起一行,为了能够在行首或者行尾添加内容还是需要使用替换模式s
二、拓展正则表达式
之前的正则表达式都需要处理完一个操作后才能接另一个操作,例如grep -v 'string1' filename|grep -v 'string2' filename十分冗长,因此有可以讲这两句合并,合并的语句为 egrep -v 'string1|string2' filename这样就可以达到相同的目的,由于grep默认是不支持拓展正则表达式的,因此要使用egrep来支持拓展正则表达式。
cat log_complex.txt|grep -v 'Epoch'|grep -v 'This fpr'
cat log_complex.txt|egrep -v 'Epoch|This fpr'
拓展的正则表达式的其他支持的操作有:
+:重复一个或者一个以上的前一个RE字符,注意与基本正则表达式*的区别。
?:重复0个或者1个前一个RE字符。
|:使用或的方式找出数个字符串
():找到组字符串
()+:多个重复组的判别
egrep 'go+d' text.txt :顺利的找到了符合要求的行,但是没有找gd
egrep 'go?d' text.txt:找到了gd和god,使用.对比一下区别能够看到区别