一、正则表达式
1. grep/egrep 工具的使用
该命令的格式为:grep [-cinvABC]‘ word' filename
,其常用的选项如下所示。
- -c:表示打印符合要求的行数。
- -i:表示忽略大小写。
- -n:表示输出符合要求的行及其行号。
- -v:表示打印不符合要求的行。
- -A:后面跟一个数字(有无空格都可以),例如-A2表示打印符合要求的行以及下面两行。
- -B:后面跟一个数字,例如-B2表示打印符合要求的行以及上面两行。
- -C:后面跟一个数字,例如-C2表示打印符合要求的行以及上下各两行。
首先看看-A、-B和-C这3个选项的用法。 - -A2会把包含halt的行以及这行下面的两行都打印出来:
- -B2会把包含halt的行以及这行上面的两行都打印出来:
- -C2会把包含halt的行以及这行上下各两行都打印出来:
1.1 过滤出带有某个关键词的行,并输出行号
示例:
1.2 过滤出不带有某个关键词的行,并输出行号
示例:
1.3 过滤出所有包含数字的行
示例:
1.4 过滤出所有不包含数字的行
示例:
1.5 过滤掉所有以#开头的行
示例:
1.6 过滤掉所有空行和#开头的行
示例:
在正则表达式中,^表示行的开始,$ 表示行的结尾,那么空行则可以用^$表示。如何打印出不以英文字母开头的行呢?我们先来自定义一个文件,如下所示:
1.7 过滤出任意一个字符和重复字符
示例:
. 表示任意一个字符。上例中,r.o 表示把 r 与 o 之间有一个任意字符的行过滤出来。
*
表示零个或多个 *
前面的字符。上例中,ooo*表示oo、ooo、oooo.. 或者更多的o
。
上例中,. *
表示零个或多个任意字符,空行也包含在内,它会把/etc/passwd文件里面的所有行都匹配到。
1.8 指定要过滤出的字符出现次数
示例:
这里用到了符号{ },其内部为数字,表示前面的字符要重复的次数。需要强调的是,{ }左右都需要加上转义字符\。另外,使用“{ }”还可以表示一个范围,具体格式为{n1,n2},其中n1<n2,表示重复n1到n2次前面的字符,n2还可以为空,这时表示大于等于n1次。
1.9 过滤出一个或多个指定的字符
示例:
和grep不同,这里egrep使用的是符号+,它表示匹配1个或多个 + 前面的字符,这个“+”是不支持被grep直接使用的。包括上面的{ } ,也是可以直接被egrep使用,而不用加\转义。示例如下:
1.10 过滤出零个或一个指定的字符
示例:
1.11 过滤出字符串 1 或字符串2
示例:
1.12 egrep中()的应用
示例:
这里用()表示一个整体,上例中会把包含rooo或者rato的行过滤出来,另外也可以把()和其他符号组合在一起,例如(oo)+就表示1个或者多个oo。如下所示:
2. sed工具的使用
2.1 打印某行
sed命令的格式为:sed -n 'n'p filename
,单引号内的n是一个数字,表示第几行。-n选项的作用是只显示我们要打印的行,无关紧要的内容不显示。示例命令如下:
可以去掉 -n 选项对比一下差异。要想把所有行都打印出来,可以使用命令sed -n '1,$'p filename
,如下所示:
也可以指定一个区间打印,如下所示:
2.2 打印包含某个字符的行
示例:
这种用法就类似于grep了,在grep中使用的特殊字符(如^、$、.、*等
)同样也能在sed中使用,如下所示:
sed命令加上 -e 选项可以实现多个行为,如下所示:
2.3 删除某些行
示例:
这里参数d表示删除的动作,它不仅可以删除指定的单行以及多行,而且可以删除匹配某个字符的行,还可以删除从某一行开始到文档最后一行的所有行。不过,这个操作仅仅是在显示器屏幕上并不显示这些行而已,文档还好好的!
2.4 替换字符或者字符串
示例:
上例中的参数s就表示替换的动作,参数g表示本行全局替换,如果不加g则只替换本行出现的第一个,这个用法其实和vim的替换大同小异。
除了可以使用/作为分隔符外,我们还可以使用其他特殊字符,例如#和@。如下所示:
删除文档中所有的数字或者字母。示例命令如下:
[0-9]表示任意的数字。这里你也可以写成[a-zA-Z]或者[0-9a-zA-Z]。如下所示:
2.5 调换两个字符串的位置
示例:
小括号在sed中属于特殊符号,必须在前面加转义字符\,替换时则写成类似\1、\2 或\3的形式。
上例中用()把想要替换的字符打包成了一个整体。有这个转义字符\,会让这个表达式看起来乱糟糟的,有个方法可以省略它。如下所示:
这个 -r 选项让这个表达式更加清晰了。除了调换两个字符串的位置,用 sed 在某一行前后增加指定内容,如下所示:
2.6 直接修改文件的内容
示例:
3. awk 工具的使用
3.1 截取文档中的某个段
示例:
本例中,-F选项的作用是指定分隔符。如果不加-F选项,则以空格或者tab为分隔符。print为打印的动作,用来打印某个字段。$1为第1个字段,$2为第2个字段,以此类推。但 $0比较特殊,它表示整行:
注意awk 的格式,-F后面紧跟单引号,单引号里面为分隔符。print的动作要用{ }括起来,否则会报错。print还可以打印自定义的内容,但是自定义的内容要用双引号括起来,如下所示:
3.2 匹配字符或者字符串
示例:
这跟sed的用法类似,能实现grep的功能,但没有颜色显示,肯定没有grep用起来方便。不过awk还有比sed更强大的匹配,如下所示:
它可以让某个段去匹配,这里的一就是匹配的意思。awk还可以多次匹配,如下所示:
本例中 awk 匹配完 root,再匹配 test,它还可以只打印所匹配的段。
3.3 条件操作符
示例:
awk中可以用逻辑符号进行判断,比如==就是等于,也可以理解为精确匹配。另外还有>、>=、<、<=、!= 等。值得注意的是,在和数字比较时,若把比较的数字用双引号引起来,那么awk不会认为是数字,而会认为是字符,不加双引号则会认为是数字:
本例中,本想把uid大于等于500的行打印出来,但是结果并不理想。这是因为awk把所有的数字当作字符了,就跟上一章中提到的sort排序原理一样。但,不加双引号就得到了想要的结果:
本例中,!=表示不匹配,它除了针对某一个段的字符进行逻辑比较外,还可以在两个段之间进行逻辑比较。如下所示:
另外还可以使用&&和 | |,它们分别表示“并且”和“或者”。&&的用法如下:
3.4 awk 的内置变量
awk常用的变量有OFS、NF和NR,OFS和-F选项有类似的功能,也是用来定义分隔符的,但是它是在输出的时候定义,NF表示用分隔符分隔后一共有多少段,NR表示行号。
OFS的用法示例:
变量NF的具体用法:
这里NF是多少段,NF是最后一段的值。变量NR的具体用法如下:
还可以使用NR作为判断条件,如下所示, NR:是指到目前为止的记录数目
NR也可以配合段匹配一起使用,如下所示:
3.5 awk 中的数学运算
awk可以更改段值,示例:
awk也可以对各个段的值进行数学运算,示例:
awk还可以计算某个段的总和,示例:
这里的END是ak特有的语法,表示所有的行都已经执行。其实 awk 连同 sed 都可以写成一个脚本文件,而且有它们特有的语法。在awk中使用 i f判断、for循环都可以,如下所示:
二、课后习题
(1)如何把 /etc/passwd 中用户 uid 大于 500的行打印出来?
答:
(2)awk中变量 NR和 NF分别表示什么含义?命令awk -F ':' '{print $NR}' /etc/passwd
会打印出什么结果?
答:NR表示行数,NF表示一共有多少段;如图:
(3)用grep把1.txt文档中包含abc或者123的行过滤出来,并在过滤出来的行前面加上行号。
答:
(4)命令grep -v '^$' 1.txt
会过滤出哪些行?
答:会过滤出不是空的行,如图:
(5)符号.、.* 和 *
分别表示什么含义?符号+和?表示什么含义?这5个符号是否可以在grep、egrep、sed 以及awk中使用?
答:
'.' 表示一个任意的字符;
'*' 表示前面紧邻的那个字符有零个或多个,即前面紧邻的那个字符可以不存在,也可以有多个;
'.*' 表示零个或多个的任意字符,包括空行;
'+' 表示前面紧邻的那个字符有一个或多个;
'?' 表示前面紧邻的那个字符有零个或一个;
grep和sed可以使用'.' 、 '*' 和 '.*',但是不能使用'+'和'?' egrep和awk全部可以使用。
(6)grep里面的符号{ }用在什么情况下?
答:{ },其内部为数字,表示前面的字符要重复的次数。数字可以是单个数字{n},也可以是一个区间{n1,n2}。在字符串中,{ }左右都需要加上脱意字符 ‘\’。
(7)sed有一个选项可以直接更改文本文件,是哪个选项?
答: -i 选项
(8)sed -i 's/.* ie//;s/["I&].*//' file
这条命令表示什么操作呢?
答:表示把file中出现的以ie结尾的字符串删除;把file中以"或|或&开头的字符串删除
(9)如何删除一个文档中的所有数字或者字母?
答:
- 删除所有数字: sed -i ‘s/[0-9]//g’ file
- 删除所有字母: sed -i ‘s/[a-Z]//g’ file
如图:
(10)截取日志1.log的第1个字段(以空格为分隔符),按数字排序,然后去重,但是需要保留重复的数量,如何做?
答:
(11)使用awk过滤出1.log中第7个字段(以空格为分隔符)为200并且第8个字段为11897的行。
答:
(12)请比较这两个命令的异同:grep -v '^[o-9]' 1.txt 和 grep '^[0-9]'
1.txt。
答:
第一个是:以数字开头的行匹配出来,输出打印剩余的行,包括空行。
第二个是:以非数字开头的行匹配出来并输出打印,不包括空行。
(13)awk中的$0表示什么?为什么以下两条命令的$0结果不一致呢?
awk -F ':' '{print $o}' 1.txt
awk -F ':' ‘$7=1 {print $o}' 1.txt
答:$0 表示整行;
- awk -F ‘:’ ‘{print $0}’ 1.txt //打印所有的行 ,即整个记录
- awk -F ‘:’ ‘$7=1 {print $0}’ 1.txt //以冒号为分隔符,输出时将每行的第七段的内容更改为1,并打印所有的行,此时并不会连带分隔符一起输出
(14)使用grep过滤某个关键词时,如何把包含关键词的行连同上面一行打印出来?连同下面一行也打印呢?同时打印上下各一行呢?
答:如图: