阶段十二:Shell脚本之Shell三剑客

一、Shell三剑客概述

1. Shell三剑客

Shell三剑客是指grep、sed和awk这三个在Linux/Unix系统中常用的命令行工具。

grep:grep 是一个文本搜索工具,用于根据给定的模式(正则表达式)在文件或输入流中搜索匹配的行。grep 的主要作用是查找和过滤特定文本。

sed:sed是一个流编辑器,可以对文本进行查找、替换、删除等操作。它可以直接在文本流中编辑,不需要打开文件,非常适合批量处理。

awk:awk 是一个文本处理工具,适合对列进行处理和分析。它不仅可以进行查找和替换,还能执行数学计算和数据统计,特别适合处理以列形式组织的数据,如日志、CSV 文件等。

面试题:grep、sed、awk有何区别?

在运维工作中,我会根据不同的需求选择合适的工具:当需要简单查找时用 grep,批量修改文件时用 sed,处理复杂的日志或统计数据时使用 awk。

2. Shell三剑客适用场景

① 日志处理与搜索:使用 grep 搜索关键词,结合 sed 和 awk 进行进一步处理和分析。

② 配置文件管理:使用 sed 和 awk 进行批量修改、添加或删除配置项。

③ 数据提取与转换:利用 awk 提取、分析和转换结构化文本数据,处理 CSV、JSON 等格式。

④ 监控与报警:使用 grep、sed 和 awk 提取关键信息生成监控报告,监控系统状态和性能。

⑤ 日常运维任务:自动化任务如查找过期文件、清理日志、统计日志大小等。

⑥ 系统管理:使用 sed 和 awk 处理系统状态信息,如用户信息、进程信息、磁盘使用情况等。

3. Shell三剑客执行说明

默认情况下,grep、sed以及awk在处理数据时默认都是按行处理

二、Shell三剑客之grep指令

1. grep基本语法

grep主要作用:过滤来自一个文件或标准输入匹配模式内容。

除了 grep 外,还有 egrep。egrep 是 grep 的扩展,相当于 grep -E。

基本语法:grep [OPTION]... PATTERN [FILE]...

支持的正则描述
-E,--extended-regexp模式是扩展正则表达式(ERE) => 字符簇、()、|或
-P,--perl-regexp模式是Perl正则表达式 => \d、\w、\s
-i,--ignore-case忽略大小写
-w,--word-regexp模式匹配整个单词
-v,--invert-match打印不匹配的行
输出控制描述
-n,--line-number打印行号
-h,--no-filename不输出文件名
-o,--only-matching只打印匹配的内容
-r,--recursive递归目录
-c,--count统计匹配行数

2. grep案例演示

准备数据集

# vim demo.txt
Hello, this is an example file.
It contains some lines of text.
Let's use grep to search for specific patterns.

命令作用:

执行结果:

关键参数:

注意事项:


**关键参数:**

**注意事项:**

关键参数:

注意事项:

注: 2代表指定对第2行操作,其他的行忽略; a代表追加的意思,2a即在第2行后追加文本; 2a后面加上空格,然后跟上你想要插入的多行文本即可。这里的每行文本使用"\n"连接就可以写成一行了。


多行增:

注:\n代表换行符

小结:

sed默认操作文件内容是在内存中的模式空间中进行实现,不会影响原文件内容。

如果希望增加操作影响原文件,可以添加一个选项-i

删除指定行文本。

这个功能也是非常得有用,比如我们想删除文件中的某些行,以前最常用的是vi或vim命令,但现在我们知道了sed命令,就应该使用这个高逼格的命令完成任务了。

这里我们需要用到1个sed命令;

"d":删除文本,记忆方法:d的全拼是delete,意思是删除。

因为删除功能比较简单,因此我们结合地址范围一起说明。我们前面学过sed命令可以对一行文本为目标进行处理(在单行前后增加一行或多行文本),接下来我们看一下如何对多行文本为目标操作。

指定执行的地址范围:

sed软件可以对单行或多行文本进行处理。如果在sed命令前面不指定地址范围,那么默认会匹配所有行。 地址用逗号分隔开,n1,n2可以用数字,正则表达式,或者二者的组合表示。


| 地址范围 | 含义 |
|---|---|
| 10 | 对第10行操作 |
| 10,20 | 对10到20行操作,包括第10,20行 |
| 1~2 | first\~step,对1,3,5,7.....行操作 |
| 10,\$ | 对10到最后一行(\$代表最后一行)操作,包括第10行 |
| /Tom/ | 对匹配Tom的行操作 |
| /Tom/,/Alex/ | 对匹配Tom的行到匹配Alex的行操作 |
| /Tom/,\$ | 对匹配Tom的行到最后一行操作 |
| 1,/Alex/ | 对第1行到匹配Alex的行操作 |

 案例1:下面用具体的例子演示一下sed删除操作实现

命令说明:如果在sed命令前面不指定地址范围,那么默认会匹配所有行,然后使用d命令删除功能就会删除这个文件的所有内容

案例2:

命令说明:这个单行删除想必大家能理解,指定删除第2行的文本


案例3:

案例4:

命令说明:在sed软件中,使用正则的格式和awk一样,使用2个"/"包含指定的正则表达式,即"/正则表达式/"。


案例5:

命令说明:这是正则表达式形式的多行删除,也是以逗号分隔2个地址,最后结果是删除包含"Tom"的行到包含"Alex"的行

案例6:

命令说明:学过正则表达式后我们知道"$"代表行尾,但是在sed中就有一些变化了,"$"在sed中代表文件的最后一行。因此本例子的含义是删除第3行到最后一行的文本,包含第3行和最后一行,因此剩下第1,2行的内容。


案例7:

命令说明:为了不造成同学们实验文本改来改去导致不同意,因此我用上面的命令语句只是临时修改内存数据,然后通过管道符号传给sed软件。

特殊符号~(步长)解析

格式:"first~step"表示从开始,以步长step递增,这个在数学中叫做等差数列 使用:


案例8:

1
2
3
4
5
6
7
8
9
10

1 3 5 7 9


命令说明:

上面的命令主要验证特殊符号"~"的效果,其他sed命令用法n和p请见后文详解,大家只需要知道这个命令可以将"1~2"指定的行显示出来即可。

上面例子测试了"1~2"的效果,大家也可以手动测试一下"2~2","1~3","2~3",看一下他们的结果是不是符合等差数列。

案例9:删除所有奇数行

命令说明:"1~2"这是指定行数的另一种格式,从第1行开始以步长2递增的行(1,3,5),因此删掉第1,3,5行,即所有的奇数行。

命令说明:在地址范围"2,3"后面加上" !",如果不加"!"表示删除第2行和第3行,结果如下面的例子所示,然后加上"!"的结果就是除了第2行和第3行以外的内容都删除,这个方法可以作为显示文件的第2,3行题目的补充方法。


小结:

sed软件不仅可以添加数据行,也可以删除数据行,删除数据行必须使用(d)命令



sed修改操作,我们最常见的操作就是改配置文件,改参数等等  
首先说一下按行替换,这个功能用的很少,所以大家了解即可。这里用到的sed命令是:"c":用新行取代旧行,记忆方法:c的全拼是change,意思是替换。

命令说明:使用sed命令c将原来第2行内容替换成106,Smith,CSO,整行替换

接下来说的这个功能,有工作经验的同学应该非常的熟悉,因为使用sed软件80%的场景就是使用替换功能。

这里用到的sed命令,选项:

"s":单独使用-->将每一行中第一处匹配的字符串进行替换-->sed命令 "g":每一行进行全部替换-->sed命令s的替换标志之一(全局替换),非sed命令 "-i":修改文件内容-->sed软件的选项,注意和sed命令i区别


sed软件替换模型


路径替换式
s#/home#/root#g

g:global全局替换
sed本身按照进行操作的,如果在1行中有多个要替换的关键词,不加g,则代表只替换满足条件第一个关键词;如果添加g,则代表替换满足条件的所有关键词!

注意事项:


**注意事项:**



这个功能也是非常得有用,比如我们想查看文件中的某些行,以前最常用的是cat或more或less命令等,但这些命令有些缺点,就是不能查看指定的行。而我们用了很久的sed命令就有了这个功能了。而且我们前面也说过使用sed比其他命令vim等读取速度更快!

这里我们需要用到1个sed命令

"p":输出指定内容,但默认会输出2次匹配的结果,因此使用-n选项取消默认输出,记忆方法:p的全拼是print,意思是打印。

案例1:

命令说明:选项-n取消默认输出,只输出匹配的文本,大家只需要记住使用命令p必用选项-n。

命令说明:

命令说明:查看文件的第2行到3行,使用地址范围"2,3"。取行就用sed,最简单


**注意事项:**

注意:起始值~步长
命令说明:打印文件的1,3,5行。~代表步长

注意事项:

命令说明:不指定地址范围,默认打印全部内容。

命令说明:

命令说明:打印含CTO的行到含CFO的行。

注意事项:

命令说明:使用特殊符号"="就可以获取文件的行号,这是特殊用法,记住即可。从上面的命令结果我们也发现了一个不好的地方:行号和行不在一行。


案例9:

命令说明:打印1,2,3行的行号,同时打印输出文件中的内容

案例10:取不连续的行


**注意事项:**



作用:awk可以完成复杂的数据分析,如日志分析等等。


awk不仅仅是Linux系统中的一个命令,更可以理解为它是一种编程语言,可以用来处理数据和生成报告(excel)。处理的数据可以是一个或多个文件,可以是来自标准输入,也可以通过管道获取标准输入,awk可以在命令行上直接编辑命令进行操作,也可以编写成awk程序来进行更为复杂的运用。本章主要讲解awk命令的运用。


awk指令是由模式,动作,或者模式和动作的组合组成。

模式既pattern,可以类似理解成sed的模式匹配,可以由表达式组成,也可以是两个正斜杠之间的正则表达式。比如NR==1,这就是模式,可以把他理解为一个条件。

动作即action,是由在大括号里面的一条或多条语句组成,语句之间使用分号隔开。

![](/assets/feishu-images/f1f725d5697d3be2249afcc7.png)

awk处理的内容可以来自标准输入(<),一个或多个文本文件或管道。

![](/assets/feishu-images/7ecafb3b058cf5ad84ee77d1.png)

options既参数,使用最多的参数为-F(Field,用于指定字段与字段之间的分隔符,列与列之间的分隔符,默认为空格)

pattern既模式,也可以理解为条件,也叫找谁,你找谁?高矮,胖瘦,男女?都是条件,既模式。

action既动作,可以理解为干啥,找到人之后你要做什么。


模式和动作的详细介绍我们放在后面部分,现在大家先对awk结构有一个了解。

案例1:基本模式与动作


命令说明:

案例2:只有模式

bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync

命令说明: -F指定分隔符为冒号 NR>=2&&NR<=6这部分是条件,表示取第2行到第6行。 但是这里没有动作,这里大家需要了解如果只有条件(模式)没有动作,awk默认输出整行


案例3:只有动作

以下省略....

命令说明:
-F指定分隔符为冒号
这里没有条件,表示对每一行都处理
这里要理解没有条件的时候,awk会处理每一行。

案例4:多模式与多动作

命令说明: -F指定分隔符为冒号 这里有多个条件与动作的组合




注意:

Pattern和{Action}需要用单引号引起来,防止Shell作解释。

Pattern是可选的。如果不指定,awk将处理输入文件中的所有记录。如果指定一个模式,awk则只处理匹配指定的模式的记录。



file要处理的目标文件


在深入了解awk前,我们需要知道awk如何处理文件的。

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin

注意事项:

bin:x:1:1:bin: daemon:x:2:2:daemon: adm:x:3:4:adm: lp:x:4:7:lp: sync:x:5:0:sync: shutdown:x:6:0:shutdown: halt:x:7:0:halt: mail:x:8:12:mail: uucp:x:10:14:uucp:

命令说明: BEGIN:开始模块,在awk开始处理数据之前执行1次 END:结束模块,在awk处理所有行后执行1次

在每行的开始先打印输出NR(记录号行号),并打印出每一行$0(整行)的内容。 我们设置RS(记录分隔符)的值为“/”,表示一行(记录)以“/”结束 在awk眼中,文件是从头到尾一段连续的字符串,恰巧中间有些\n(回车换行符),\n也是字符哦。


我们回顾下“行(记录)”到底是什么意思?

行(记录):默认以\n(回车换行)结束。而这个行的结束不就是记录分隔符嘛。

所以在awk中,RS(记录分隔符)变量表示着行的结束符号(默认是回车换行)

在工作中,我们可以通过修改RS变量的值来决定行的结束标志,最终来决定“每行”的内容。

为了方便人们理解,awk默认就把RS的值设置为“\n”

注意:

awk的BEGIN模块,我会在后面(模式-BEGIN模块)详细讲解,此处大家仅需要知道在BEGIN模块里面我们来定义一些awk内置变量即可。

对\$0的认识


NR:行号,打印行号

\$NF:NF代表列号,如果前面添加了\$,则代表最后一列

\$0:整行内容

\$1:按照-F分割后,\$1代表分割后的第1列

\$2:按照-F分割后,\$2代表分割后的第2列

由以上代码运行可知:awk中\$0表示整行,其实awk使用\$0来表示整条记录。记录分隔符存在RS变量中或者说每个记录以RS内置变量结束。

另外,awk对每一行的记录号都有一个内置变量NR来保存,每处理完一条记录,NR的值就会自动+1

案例2:NR记录行号


命令说明:
$0表示整行或者说整个记录

企业面试题:按单词出现频率降序排序(计算文件中每个单词的重复数量)


**注意事项:**

方案二:


**注意事项:**



基本语法:


分隔符,需不需要根据某个符号提取某1列

NR存放着每个记录的号(行号)读取新行时候会自动+1

RS是输入数据的记录的分隔符,简单理解就是可以指定每个记录的结尾标志。

RS作用就是表示一个记录的结束

当我们修改了RS的值,最好配合NR(行)来查看变化,也就是修改了RS的值通过NR查看结果,调试awk程序。

ORS输出数据的记录的分隔符

awk学习技巧一则:

大象放冰箱分几步?打开冰箱,把大象放进去,关闭冰箱门。

每条记录都是由多个区域(field)组成的,默认情况下区域之间的分隔符是由空格(即空格或制表符)来分隔,并且将分隔符记录在内置变量FS中,每行记录的区域数保存在awk的内置变量NF中。

image

OFS输出字段(列)分隔符

案例1:指定分隔符

命令说明: 以:(冒号)为分隔符,显示第2行到第5行之间的第一区域和第三区域。


案例2:提取字符串中的内容

注意事项:

命令说明: 通过命令-F参数指定区域分隔符


小技巧:




#默认分隔符时候

#指定分隔符时候


命令说明:
awk默认的FS分隔符对于空格序列,一个空格或多个空格tab都认为是一样的,一个整体。

注意事项:

awk无比强大,你可以通过RS,FS决定awk如何读取数据。你也可以通过修改ORS,OFS的值指定awk如何输出数据。

image

现在你应该会对awk的记录字段有所了解了,下面我们总结一下,学会给阶段性知识总结是学好运维的必备技能。

image

RS记录分隔符,表示每行的结束标志

NR行号(记录号)

FS字段分隔符,每列的分隔标志或结束标志

NF就是每行有多少列,每个记录中字段的数量

\$符号表示取某个列(字段),\$1\$2\$NF

NF表示记录中的区域(列)数量,\$NF取最后一个列(区域。)

选好合适的刀FS,RS,OFS,ORS

分隔符==>结束标识

记录与区域,你就对我们所谓的行与列,有了新的认识(RS,FS)

awk模式与动作

接下来就详细介绍下,awk的模式都有几种:

案例1:awk正则表达式匹配整行


命令解析:

awk只用正则表达式的时候是默认匹配整行的即‘\$0\~/root/’和‘/root/’是一样的。

案例2:awk正则表达式匹配一行中的某一列

命令解析:

\$5表示第五个区域(列)

\~表示匹配(正则表达式匹配)

/shutdown/表示匹配shutdown这个字符串

合在一起,\$5\~/shutdown/表示第五个区域(列)匹配正则表达式/shutdown/,既第5列包含shutdown这个字符串,则显示这一行。

案例3:某个区域中的开头和结尾

知道了如何使用正则表达式匹配操作符之后,我们来看看awk正则与grep和sed不同的地方。

awk正则表达式:

^匹配一个字符串的开头
\$匹配一个字符串的结尾

数据集


**注意事项:**

练习题2:显示Xiaoyu的名字和ID号码,并以逗号隔开


练习题3:显示所有以41开头的ID号码的人的全名和ID号码

练习题4:显示所有以一个D或X开头的人名全名


练习题5:显示所有ID号码最后一位数字是1或5的人的全名

案例4:取出网卡ens33/ens160的ip地址

注意事项:

命令解析: |是或者的意思,正则表达式 sort是将输出结果排序 uniq是去重复但不标记重复个数


**注意事项:**



![](/assets/feishu-images/d79e183ac55bc6871cc32674.png)


BEGIN模块再awk读取文件之前就执行,一般用来定义我们的内置变量(预定义变量,eg:FS,RS),可以输出表头(类似excel表格名称)

BEGIN模式之前我们有在示例中提到,自定义变量,给内容变量赋值等,都使用过。需要注意的是BEGIN模式后面要接跟一个action操作块,包含在大括号内。awk必须在输入文件进行任何处理前先执行BEGIN里的动作(action)。我们可以不要任何输入文件,就可以对BEGIN模块进行测试,因为awk需要先执行完BEGIN模式,才对输入文件做处理。BEGIN模式常常被用来修改内置变量ORS,RS,FS,OFS等值。

案例1:可以使用BEGIN设定表头信息

说明:

要在第一行输出一些username和UID,我们应该想到BEGIN{}这个特殊的条件(模式),因为BEGIN{}在awk读取文件之前执行的。

案例2:awk变量

直接定义,直接使用即可

awk命令不仅可以进行数据获取分析,还支持数学运算!

awk中字母会被认为是变量,如果真的要给一个变量赋值字母(字符串),请使用==双引号==

123456



作用:与BEGIN相呼应,在awk处理文件结束后,会自动触发END模块(只会触发1次)

案例1:统计/etc/servies文件里的空行数量

思路:



grep方法:

16

16

说明:
grep命令-c表示count计数统计包含^$的行一共有多少。

注意事项:


提示:

使用了awk的技术功能,很常用

第一步:统计空行个数

/^$/表示条件,匹配出空行,然后执行{i++}(i++等于i=i+1)即:/^$/{i=i+1}

第二步:

awk编程思想: 先处理,最后再END模块输出


案例2:awk支持数学运算

注意事项:



awk提供了"数组"来存放一组相关的值。

awk是一种编程语言,肯定也支持数组的运用,但是又不同于c语言的数组。数组在awk中被称为关联数组,因为它的下标既可以是数字也可以是字符串。下标通常被称作key,并且与对应的数组元素的值关联。数组元素的key和值都存储在awk程序内部的一张表中,通过一定散列算法来存储,所以数组元素都不是按顺序存储的。打印出来的顺序也肯定不是按照一定的顺序,但是我们可以通过管道来对所需的数据再次操作来达到自己的效果。

![](/assets/feishu-images/481dfcada7eb5d3bed535945.jpg)

students[a]="张三"

students[b]="李四"

students[c]="王五"


白话讲数组:awk数组就和酒店一样。数组的名称就像是酒店名称,数组元素名称就像酒店房间号码,每个数组元素里面的内容就像是酒店房间里面的人。

假设我们有一个酒店:

酒店<===>hotel

酒店里面有几个房间110,119,120,114这几个房间

酒店110房间<===>hotel[110] 酒店120房间<===>hotel[120] 酒店119房间<===>hotel[119] 酒店114房间<===>hotel[114]


酒店房间入驻客人

酒店110房间住着xiaoyu<===>hotel[110]="xiaoyu"
酒店119房间住着ruxue<===>hotel[119]="ruxue"
酒店120房间住着dandan<===>hotel[120]="dandan"
酒店114房间住着bingbing<===>hotel[114]="bingbing"

案例1:


案例2:

案例3:统计域名访问次数

http://www.itheima.com/index.html http://www.itheima.com/1.html http://post.itheima.com/index.html http://mp3.itheima.com/index.html http://www.itheima.com/3.html http://post.itheima.com/2.html


**注意事项:**

第二步:计数

命令说明: i++:i最开始是空的,当awk读取一行,i自身+1


第三步:用数组替换i


命令说明:

2)h[$2]++就等于i++:也就是说我开始给房间里加东西;当出现同样的东西,我就++
4)综上,输出的结果中,每次出现www.itheima.com时,h["www.itheima.com"]就会++。因此最后的输出数字是3

第四步:输出最终计数结果

h[www.itheima.com]=3 h[post.itheima.com]=2 h[mp3.itheima.com]=1

http://www.itheima.com/index.html http://www.itheima.com/1.html http://post.itheima.com/index.html http://mp3.itheima.com/index.html http://www.itheima.com/3.html http://post.itheima.com/2.html

针对以上文件,一行一行读取 读取第1行,发现与www.itheima.com这个索引对应的数组元素一致,进行+1 读取第2行,发现与www.itheima.com这个索引对应的数组元素一致,进行+1 ...



本文由飞书云文档同步生成。涉及命令、SQL、配置示例时,请以飞书源文档和实际环境执行结果为准。