shell 编程之sed工具以及awk工具的用法示例 结合实例理解简单

一、了解sed工具

1、sed工具的介绍

sed(Stream EDitor)是一个强大而简单的文本解析转换工具,可以读取文本,并根据指定的条件对文本内容进行编辑(删除、替换、添加、移动等),最后输出所有行或者仅输出处理的某些行。sed 也可以在无交互的情况下实现相当复杂的文本处理操作,被广泛应用于 Shell 脚本中,用以完成各种自动化处理任务。

sed是一种流编辑器,流编辑器会在编辑处理数据之前基于预先提供的一组规则来编辑数据流。

sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中。
sed 的工作流程主要包括读取、执行和显示三个过程。

  • 读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
  • 执行:默认情况下,所有的 sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则 sed 命令将会在所有的行上依次执行。
  • 显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。
2、使用sed的注意事项

在使用sed命令处理文件时,在所有的文件内容都被处理完成之前,上述过程(读取、执行、显示)将重复执行,直至所有内容被处理完。

默认情况下所有的sed命令都是在缓存空间内执行的,因此文件本身的并不会因为sed命令发生任何变化,除非使用了重定向符将编辑后的文件从新存储输出到新的文件
例如,使用sed命令将/etc/passwd文件中的所有信息删除,在从新查看etc/passwd文件中的内容,发现并没有删除。

[root@localhost ~]# sed 'd' /etc/passwd      //使用sed命名删除/etc/passwd中所有的内容
[root@localhost ~]# cat /etc/passwd           //查看etc/passwd中的内容  
root:x:0:0:root:/root:/bin/bash          //所有内容都还在  说明使用sed命令不能改变源文件
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
...........        省略部分内容
3、sed 命令常见用法

通常情况下调用 sed 命令有两种格式:
sed [选项] ‘操作’ 参数
sed [选项] -f scriptfile 参数

  • 其中,“参数”是指操作的目标文件, 当存在多个操作对象时用,文件之间用逗号“,”分隔;
  • 而 scriptfile 表示脚本文件,需要用“-f” 选项指定,当脚本文件出现在目标文件之前时,表示通过指定的脚本文件来处理输入的目标文件。
4、常见的 sed 命令 选项
选项 注释
-f 或–file= 表示用指定的脚本文件来处理输入的文本文件。
-e 或–expression= 表示用指定命令或者脚本来处理输入的文本文件。
-h 或–help 显示帮助。
–quiet 或 silent 表示仅显示处理后的结果。
-i 直接编辑文本文件。
5、常见的 sed 命令 操作
操作 注释
a 增加,在当前行下面增加一行指定内容。
c 替换,将选定行替换为指定内容。
d 删除,删除选定的行。
i 插入,在选定行上面插入一行指定内容。
p 打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用。
s 替换,替换指定字符。
y 字符转换。
l 打印数据流中的文本和不可打印的 ASCII字符(比如结束符%、制表符 \t)

二、sed工具的用法示例

1、输出指定的行(p 表示正常输出)

1.1、sed的基本用法

[root@localhost ~]# sed -n 'p' /etc/passwd   //输出所有内容,等同于 cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
..........        //省略部分信息
[root@localhost ~]# sed -n '3p' /etc/passwd    //输出第三行的内容
daemon:x:2:2:daemon:/sbin:/sbin/nologin

[root@localhost ~]# sed -n '3,5p' /etc/passwd   //输出3到5行的内容
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

[root@localhost ~]# sed -n 'p;n' /etc/passwd 
//输出文本的奇数行,p打印第一行,n表示读入下一行的内容,没有输出,以此类推,就输出了全部的奇数行
root:x:0:0:root:/root:/bin/bash
daemon:x:2:2:daemon:/sbin:/sbin/nologin
..........        //省略部分信息

[root@localhost ~]# sed -n 'n;p'  /etc/passwd
//输出文本的偶数行,n表示读入下一行的内容,没有输出,p打印第二行的内容,以此类推,就输出了全部的偶数行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
..........        //省略部分信息

[root@localhost ~]# sed -n '1,5{p;n}' /etc/passwd      //输出第 1~5 行之间的奇数行(第 1、3、5 行) 

[root@localhost ~]# sed -n '10,${n;p}' /etc/passwd    //输出第 10 行至文件尾之间的偶数行
//在执行“sed -n‘10,${n;p}’test.txt”命令时,读取的第 1 行是文件的第 10 行,
//读取的第 2行是文件的第 11 行,依此类推,所以输出的偶数行是文件的第 11 行、13 行直至文件结尾, 
//其中包括空行。

1.2、sed结合正则表达式的用法

[root@localhost ~]# sed -n '/root/p' /etc/passwd     //输出含有root字段的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@localhost ~]# sed -n '2,/root/p' /etc/passwd  //输出从第2 行开始直到含有root的的行停止
bin:x:1:1:bin:/bin:/sbin/nologin  //第二行开始
..........        //省略部分信息
operator:x:11:0:operator:/root:/sbin/nologin   //直到含有root的行停止输出
        
[root@localhost ~]# sed -n '/root/=' /etc/passwd   //显示含有root行的行号
1
10

[root@localhost ~]# sed -n '/[0-5]/p' /etc/passwd     //输出含有数字1到5之间的行
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin 
..........        //省略部分信息     

[root@localhost ~]# sed -n '/\<root\>/p' /etc/passwd     //输出包含单词root的行, \<、\> (固定格式)代表单词边界
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin                                         
2、删除符合条件的行(d删除)
[root@localhost ~]# sed 'd' /etc/passwd   //删除所有行

[root@localhost ~]# sed '5d' /etc/passwd  //删除第5行

[root@localhost ~]# sed '5,10d' /etc/passwd  //删除5到10行

[root@localhost ~]# sed '/root/d' /etc/passwd  //删除含有root的字符的行

[root@localhost ~]# sed '/root/! d' /etc/passwd   //删除除了包含root的所有行

[root@localhost ~]# sed '/^[A-Z]/d' /etc/passwd   //删除以大写字母开头的行

[root@localhost ~]# sed '/[a-z]$/d' /etc/passwd  //删除以小写字母结尾的行

[root@localhost ~]# sed '/^$/d' /etc/passwd	//删除所有空行

[root@localhost ~]# sed '/root/,/the/d' /etc/passwd  
//从匹配第一个位置打开删除行功能,到匹配到第二个位置关闭删除功能
[root@localhost ~]# sed -e '/^$/{n;/^$/d}'  /etc/passwd 
//删除重复的空行,即连续的空行只保留一个,只能用于删除连续两行的空行中的一行。
3、替换符合条件的内容(s(字符串替换))
[root@localhost ~]# sed 's/^/#/' /etc/passwd	//在每行行首插入#号

[root@localhost ~]# sed 's/$/#/' /etc/passwd	//在每行行尾插入#

[root@localhost ~]# sed 's/root/ROOT/g' /etc/passwd	//将文件中的所有root 替换为 ROOT
//g:表明新字符串将会替换所有匹配的地方
[root@localhost ~]# sed 's/i/I/2' /etc/passwd	//将每行中的第 2 个 i替换为 I
//数字:表明新字符串将替换第几处的匹配的地方
[root@localhost ~]# sed 's/root/ROOT/' /etc/passwd	//将每行中的第一个root 替换为 ROOT

[root@localhost ~]# sed '5,10s/root/ROOT/g' /etc/passwd	//将第 5~10 行中的所有 root 替换为 ROOT

[root@localhost ~]# sed '/root/s/o/O/g' /etc/passwd	//将包含root 的所有行中的 o 都替换为 O

[root@localhost ~]# sed -n '9s/root/ROOT/p' /etc/passwd	//将第 9行中的所有 root 替换为 ROOT
p:打印与替换命令匹配的行,与-n一起使用
4、移动符合条件的内容

移动符合条件常用的参数

常用的参数 注释
H 复制到剪贴板
G 将剪贴板中的数据覆盖/追加至指定行
w 保存为文件
r 读取指定文件
a 追加指定内容
sed '3aNew' /etc/passwd//在第 3 行后插入一个新行,内容为New

sed '/the/aNew' /etc/passwd	//在包含the 的每行后插入一个新行,内容为 New

sed '3aXIN1\nXIN2' /etc/passwd	//在第 3 行后插入多行内容,中间的\n 表示换行

sed '/the/{H;d};$G' /etc/passwd	//将包含the 的行迁移至文件末尾,{;}用于多个操作

sed '1,5{H;d};17G' /etc/passwd	//将第 1~5 行内容转移至第 17 行后

sed '/root/w wu.txt' /etc/passwd	//将包含the 的行另存为文件 wu.txt

sed '/the/r /etc/hostname' /etc/passwd	//将文件/etc/hostname 的内容添加到包含 the 的每行以后

5、使用脚本编辑文件
[root@localhost mail]# sed '5,10{H;d};17G' /etc/passwd 	//将第 5~10 行内容转移至第 25 行后
[root@localhost mail]# vim 55    //编辑一个简单的操作动作文件
5,10H   //将5到10行复制到剪切板
5,10d   //将5到10行删除
25G     //将剪切板的内容粘贴到25行的后面
[root@localhost mail]#  sed -f 55 /etc/passwd    //通过sed调用文件完成编辑
..........        //省略部分信息 
6、sed脚本应用案例

编写一个脚本,用来调整 vsftpd 服务配置,要求禁止匿名用户,但允许本地用户登录,且具有写入权限。

[root@localhost ~]# vim ftp.sh
#!/bin/bash
//配置文件路径
CONFIG="/etc/vsftpd/vsftpd.conf"   
//cp 命令对源行文件备份
[ -e "$CONFIG.old" ] || cp $CONFIG $CONFIG.old
//修改配置文件
sed -e '/^anonymous_enable/s/YES/NO/g' $CONFIG  //禁止匿名用户
sed -i -e '/^local_enable/s/NO/YES/g' -e '/^write_enable/s/NO/YES/g' $CONFIG//允许本地用户读写
sed -i '/^lisent/s/NO/YES/g' $CONFIG  //开启监听端口
//启动vsftpd 服务,并设为开机后自动运行
systemctl restart vsftpd 
systemctl enable vsftpd

三、了解awk工具

1、awk 常用格式

通常情况下 awk 所使用的命令格式如下所示,其中,单引号加上大括号“{}”用于设置对数据进行的处理动作。awk 可以直接处理目标文件,也可以通过“-f”读取脚本对目标文件进行处理。

awk 选项 '模式或条件 {编辑指令}' 文件 1 文件 2 …  //过滤并输出文件中符合条件的内容
awk   -f   脚本文件 文件 1 文件 2 …	  //从脚本中调用编辑指令,过滤并输出内容
2、awk 的执行方式

前面提到 sed 命令常用于一整行的处理,而 awk 比较倾向于将一行分成多个“字段”然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。在使用 awk 命令的过程中,可以使用逻辑操作符“&&”表示“与”、“||” 表示“或”、“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。

awk 从输入文件或者标准输入中读入信息,与 sed 一样,信息的读入也是逐行读取的。不同的是 awk 将文本文件中的一行视为一个记录,而将一行中的某一部分(列)作为记录中的一个字段(域)。为了操作这些不同的字段,awk 借用 shell 中类似于位置变量的方法, 用$1、$2、$3…顺序地表示行(记录)中的不同字段。另外 awk 用$0 表示整个行(记录)。不同的字段之间是通过指定的字符分隔。awk 默认的分隔符是空格。awk 允许在命令行中用“-F 分隔符”的形式来指定分隔符。
例如,执行 awk -F ‘:’ ‘{print $1,$3,$4}’ /etc/passwd 命令时,处理的流程如下图。最够一行为获取到的结果。
在这里插入图片描述

3、awk可以直接使用的常见内置变量
内置变量 注释
FS 指定每行文本的字段分隔符,默认为空格或制表位。
NF 当前处理的行的字段个数。
NR 当前处理的行的行号(序数)。
$0 当前处理的行的整行内容。
$n 当前处理行的第 n 个字段(第 n 列)。
FILENAME 被处理的文件名。
RS 数据记录分隔,默认为\n,即每行为一条记录。

四、awk工具的用法示例

1、按行输出文本

输出所有内容,等同于 cat test.txt

[root@localhost ~]# awk '{print}' /etc/passwd     //输出全部行
[root@localhost ~]# awk '{print $0}' /etc/passwd    //输出全部行

输出固定行数的内容

[root@localhost ~]# awk 'NR==1,NR==3{print}' /etc/passwd         //输出第 1~3 行内容
[root@localhost ~]# awk '(NR>=1)&&(NR<=3){print}' /etc/passwd  	//输出第 1~3 行内容
[root@localhost ~]# awk 'NR==1||NR==3{print}' /etc/passwd    	//输出第 1 行、第 3 行内容

输出基数和偶数行

[root@localhost ~]# awk '(NR%2)==1{print}' test.txt	//输出所有奇数行的内容
[root@localhost ~]# awk '(NR%2)==0{print}' test.txt	//输出所有偶数行的内容

输出以什么开头和结尾的行

[root@localhost ~]# awk '/^root/{print}' /etc/passwd	//输出以root 开头的行
[root@localhost ~]# awk '/nologin$/{print}' /etc/passwd	//输出以 nologin 结尾的行

统计awk过滤的行数

[root@localhost ~]# awk 'BEGIN {x=0};/\/bin\/bash$/{x++};END {print x}' /etc/passwd
//awk执行的顺序是,首先执行BEGIN{}中的操作;然后从指定的文件中逐行读取数据,
自动更新NF、NR、$0、$1等内建变量值,如执行‘模式或条件{编辑指令}’;最后执行
END{}中的后续操作。
相当于开始位和结束位
//统计以/bin/bash 结尾的行数,等同于 grep -c "/bin/bash$" /etc/passwd
[root@localhost ~]# awk 'BEGIN{RS=""};END{print NR}' /etc/passwd
//统计以空行分隔的文本段落数
2、按字段输出文本
awk '{print $3}'  /etc/passwd          //输出每行中(以空格或制表位分隔)的第 3 个字段
awk '{print $1,$3}'  /etc/passwd	                //输出每行中的第 1、3 个字段
awk -F ":" '$2==""{print}' /etc/shadow             //输出密码为空的用户的shadow 记录
awk 'BEGIN {FS=":"}; $2==""{print}' /etc/shadow   //输出密码为空的用户的shadow 记录
awk -F ":" '{print NR, $0}' /etc/passwd    //输出处理数据的行号,每处理完一条记录,NR值加一
awk -F ":" '$3<5 {print $1 $3}' /etc/passwd  //输出第三列小于5的第一列与第三列的数据
awk -F ":" 'NR==1,NR==7{print $1,$7}' /etc/passwd  
//输出第三行到第七行中以冒号为分割符的第1列和第7列的数据
awk -F ":" '$7~"/bash"{print $1}' /etc/passwd
//输出以冒号分隔且第 7 个字段中包含/bash 的行的第 1 个字段
awk '($1~"nfs")&&(NF==7){print $1,$2}' /etc/passwd
//输出包含 7 个字段且第 1 个字段中包含 nfs 的行的第 1、2 个字段
awk -F ":" '($7!="/bin/bash")&&($7!="/sbin/nologin"){print}' /etc/passwd
//输出第 7 个字段既不为/bin/bash 也不为/sbin/nologin 的所有行

  输出的数据可以插入文本标签,用双引号括起来放到变量前
awk -F ":" 'NR==1,NR==7{print "第1位:"$1,"第7位:"$7}' /etc/passwd                  
第1位:root 第7位:/bin/bash  
..........        //省略部分信息   
3、awk使用条件表达式
awk -F ":" '{if($3>200){print $-}}' /etc/passwd  //输出第3个字段大于200的行
awk -F ":" '{max=($3>$4) ? $3:$4; print max}' /etc/passwd
//如果第3个字段的值大于第4个字段的值,则把问好前表达式的值赋给max,否者就就将
冒号后那个表达式的值赋给max
awk -F ":" '{max=($3>200)? $3:$1;print max}' /etc/passwd
//如果第3个字段的值大于200,则把第3个字段的值赋给max,否者就将第1个字段的值赋给max
4、awk使用管道符号
awk -F: '/bash$/{print | "wc -l"}' /etc/passwd
//调用wc -l 命令统计使用 bash 的用户个数,等同于 grep -c "bash$" /etc/passwd
awk 'BEGIN {while ("w" | getline) n++ ; {print n-2}}'
//调用w 命令,并用来统计在线用户数
awk 'BEGIN { "hostname" | getline ; print $0}'
//调用hostname,并输出当前的主机名
//当getline左右无重定向符"<""|"时,getline则作用于当前文件,读入当前文件的第一行给其后跟的变量var或$1;
应该注意到,由于awk在处理getline之前已经读入了一行,所以getline得到的返回结果是隔行的。
当getline左右有重定向符"<""|"时,getline则作用于定义输入文件,由于该文件是刚打开的,
并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。
5、awk自定义分隔符过滤信息

例如;将文本55.txt中的字符串“http://www.55xuexi.ed/root/456.html";分段过滤出"http:"、“www.55xuexi.eda”、“root”、“456.htm”、"456"输出。

[root@localhost ~]# awk -F "//" '{print $1}' /root/55.txt
http:
[root@localhost ~]# awk -F "/" '{print $3}' /root/55.txt  
www.55xuexi.ed
[root@localhost ~]# awk -F "/" '{print $4}' /root/55.txt 
root
[root@localhost ~]# awk -F "root/" '{print $2}' /root/55.txt 
456.html
[root@localhost ~]# awk -F "." '{print $3}' /root/55.txt|awk -F "/" '{print $3}'
456
6、awk 脚本应用案例

脚本用来实现对磁盘空间的使用超过90%则发E-mail报警。

#!/bin/bash
#监视可用磁盘空间
#monitor available disk space
#截取以“/”为结尾的行,打印第5个字段也就是跟分区使用百分比,截取掉“%”
K=`df | sed -ne '/\/$/ p' | awk '{print $5}'| sed 's/%//'`
if [ $K -ge 90 ]    //如果占比超过90就向管理员发报警邮件
then
echo "磁盘可用空间报警" | mail -s "磁盘报警"[email protected]
fi
//可以将此脚本放到周期性任务列表里定时检查磁盘空间使用情况

猜你喜欢

转载自blog.csdn.net/wulimingde/article/details/108184367