快速了解shell编程语言,及shell脚本编写使用(5)

 shell脚本编程(5)——shell三剑客(grep、sed、awk)

这一章主要写的是linux系统三大文本处理工具grep、sed及awk的介绍以及各自优缺点,能够

快速掌握在文本中过滤,编辑,格式化的一些快捷功能(* ^ - ^ *)

目录

 shell脚本编程(5)——shell三剑客(grep、sed、awk)

一、grep过滤工具

1、grep概述

2、egrep用法

二、sed流式编辑器

1、sed概述

2、sed命令格式解析

 


一、grep过滤工具

1、grep概述

  • grep全称是Global Regular Expression Print

  • grep命令是一款强大的文本搜索工具

  • 他能使用用正则表达式搜素文本,并把匹配的行打印出来(使用正则表达式需要转义符号( 反斜杠\ ))

  • 它的使用权限是所有用户。
  • 格式: grep  “ 查找条件”    文件名

2、egrep用法

  • 使用正则表达式不需要用转义符号( 反斜杠\ )

  • egrep过滤工具   =   grep  -E

  • 常用的命令选项

i  :忽略字母大小写

v  :条件取反

c  :统计匹配的行数

q  :静默、无任何输出,一般用于检测(用$?检测 )

n  :显示出匹配结果所在的行号

--color :标红色显示匹配的字符串

  • grep具体用法看上一篇文章

二、sed流式编辑器

1、sed概述

  • sed全称是:Stream Editor(流式编辑器)

  • 逐行处理,并将结果输出到屏幕

  • 可以非交互式实现增删改查,逐行处理

  • 可实现对文本的输出、删除、替换、复制、剪切、导入、导出等各种操作

2、sed命令格式解析

  • 主要用法:两种

格式1:前置命令 | sed [选项]  ‘编辑指令’                 #执行完上条命令后管道给sed命令处理

格式2:sed  [选项]  ‘编辑指令’  文件…                    #直接编辑文件

  • 常见命令选项

-n 屏蔽默认输出(全部文本)

-i 直接修改文本内容

-r 启用扩展正则表达式,若与其他选项一起用,应作为首个选项

  • 常用的动作指令行

p 打印行

sed -n ‘1p’ a.txt                                                                    //查看文本的第1行

sed -n ‘1,3p’ a.txt                                                                 //查看文档第1到3行

sed -n ‘1,+3p’ a.txt                                                              //查看文档第1-4行

sed -n ‘1p,5p’ a.txt                                                              //查看第1和第5行

sed -n ‘1~2p’ a.txt                                                               //查看奇数行

sed -n ‘2~2p’ a.txt                                                               //查看偶数行

sed -n ‘=’ a.txt                                                                     //查看行号

sed -n ‘$=’ a.txt                                                                  //查看最后一行的行号

sed -n ‘$p’ a.txt                                                                  //查看最后一行

使用正则表达式做定址符:

sed -n '/root/p' user                                                           //输出有root的行

sed -n '/^bin/p' user                                                           //输出以bin开头的行sed -n '/root/!p' user    输出没有root的行

d 删除行

sed ‘d’ a.txt                                                                        //删除所有行

sed ‘1d’ a.txt                                                                      //删除第一行

sed ‘1,3d’ a.txt                                                                  //删除第1到第3行

sed ‘1,+3d’ a.txt                                                                //删除第1第4行

sed ‘1d,3d’ a.txt                                                               //删除第一和第三

sed '1~2d' a.txt                                                                //删除奇数行

sed '2~2d' a.txt                                                                //删除偶数行

sed '$d' a.txt                                                                   //删除最后一行

使用正则表达式做定址符:

sed  '/root/d' user                                                           //删除有root的行

sed  '/root/!d' user                                                          // 删除没有root的行

s 字符串替换

(替换分隔符“/” “s/old/new/”    “/g”代表所有替换)

(使用\1标签可调用本组表达式内的第一个用()保存的结果)

(使用#来分隔带/的目录名 ‘s#/bin/bash#/mnt/xixi#’  \为转义符号)

sed  's/2017/XXXX/'  a.txt                                             //替换所有行的第1个2017为XXXX

sed  's/2017/XXXX/2'  a.xtx                                          //替换所有行的第2个2017为XXXX

sed  's/2017/XXXX/g'  a.xtx                                          //替换所有行的所有2017为XXXX

sed  '1s/2017/XXXX/'  a.xtx                                          //替换第1行的第1个2017

sed  '1,2s/2017/XXXX/'  a.xtx                                      //替换第1~2行的第1个2017

sed  '2,+1s/2017/XXXX/'  a.xtx                                    //替换第2行以及后面1行的第1个2017

sed  '/2024/s/2017/XXXX/'  a.xtx                                 //替换有2024的行的第1个2017

sed  '1s/2017/XXXX/;3s/2017/XXXX/'  a.xtx               //替换第1行和第3行的2017

  • /bin/bash 替换成 /sbin/sh(\转义符号)

sed 's/\/bin\/bash/\/sbin\/sh/' user    方案一

sed 's#/bin/bash#/sbin/sh#' user        方案二

  • 文本块处理动作符

 i 在行的上面插入文本

sed '/root/i 666' user                                                     //有root的行上添加666

sed '2i 666' user                                                           //第2行上添加666

 a 在行的下面插入文本

sed 'a 666' user                                                          //所有行下追加666

sed '1a 666' user                                                        //第1行下追加666

sed '/root/a 666' user                                                  //有root的行下追加666

 c 替换整行

sed '3c 666' user                                                        //第3行替换为666

sed 'c 666' user                                                           //所有行替换为666

  • 文件导入导出

r 读取文件       (结合-i选项才会存入,否则只输出)

sed  ‘2r a.txt’  user                                                       //在第二行下插入a.txt文件

sed  ‘/^abc/r a.txt’  user                                               //在含abc开头的行下插入a.txt文件

w 保存到文件   (动作以覆盖的方式另存为新文件)

sed -n ‘1,2w a.txt’ user                                               //将第一到第二行另存为a.txt文件

sed -n ‘/^XX/w a.txt ’ user

sed -n ‘/^XX/p’ user > a.txt                                         //效果同上 ,将以XX开头的行另存为a.txt文件

  • sed流控制

! 取反操作  (用途:根据地质条件取反)

sed -n ‘/bash$/!p’  /etc/passwd                                //列出不使用bash的用户账号记录

3、sed综合脚本应用

  • 按照 "用户名 --> 密码" 的格式输出使用bash做解释器的用户信息
    #!/bin/bash
    u=`sed -n '/bash$/s/:.*//p' /etc/passwd`    //提取使用bash的用户名称
    for i in $u                                 //将使用bash的用户交给for循环
    do
    p=`grep "$i" /etc/shadow`                   //找出shadow文件中对应的用户的行
    p1=${p#*:}                                  //将此行掐头
    p2=${p1%%:*}                                //再去尾,得到密码信息
    echo "$i --> $p2"                          //按需求输出
    done
    

     

 

三、awk格式化工具

1、awk工具概述

  • AWK是一个优良的文本处理工具、awk编程语言/数据处理引擎
  • Linux及Unix环境中现有的功能最强大的数据处理引擎之一。

          创造者:Aho、Weinberger、Kernighan (以三位创作者首字母命名)

          基于模式匹配检查输入文本,逐行处理并输出

          通常用在shell脚本红,获取指定的数据

          单独使用时。可对文本数据做统计(不能修改文本的内容)

2、命令格式解析

  • 主要用法(两种)

格式①:前置命令 |  [选项]  ‘[条件]{指令}’

格式②awk [选项]  ‘ [条件]{指令}’ 文件名…

{指令}:多条语句可以用分号分隔、print是最常用的指令

[选项]:  -F  :指定分隔符,默认可以省略(默认为空格或Tab位)

  • awk内置变量(有特殊含义,可以直接使用)

变量用途
FS 保存活设置字段分隔符,例如FS=":"  与-F功能一样
$n

指定分隔的第n哥字段,如字段$1、$3分别表示第1、第三列

$0当前读入的整行文本内容
NF记录当前处理行的字段个数(列数)
NR

记录当前已读入行的数量(行数)

 

 

 

 

 

 

 

 

awk '{print $1,$2,$3}' test                                     //输出1~3列

awk '{print $3}' test                                              //输出第3列

awk '{print $0}' test                                              //输出文档原内容

awk '{print $1,$0}' test                                         //输出第1列,再加文档原内容

awk '{print NR}' test                                             //输出每行的行号

awk '{print NF}' test                                            // 输出每行有多少列

awk '{print $NF}' test                                          // 输出每行有最后一个字段

awk '{print "test"}' test                                         //输出常量test

awk '{print "test"$1 }' test                                    //常量+变量混合输出

awk '{print test }' test                                           //不加双引号,识别为变量,未定义的变量内容为空

awk -F: '{print $1}' /etc/passwd                            //定义冒号为分隔符,输出第1列

awk -F: '{print $1"的解释器是"$7}' user                //定义新分隔符后,输出常量+变量(常量加双引号)

  • awk工作流程的控制

格式:awk  [选项]  ' BEGIN{指令} {指令} END{指令}'  文件

BEGIN{ } 行前处理,读取文件内容前执行,指令执行1次

{ } 逐行处理,读取文件过程中执行,指令执行n次

END{ } 行后处理,读取文件结束后执行,指令执行1次

  • 案例1 :按格式输出文档内容


awk -F: 'BEGIN{print "User\tUID\tHome"}{print $1"\t"$3"\t"$6}END{print "总计"NR"行"}'/etc/passwd

 a先输出首行为User  UID  Home(\t代表是自动空格对齐)

b再输出每行的第一第三第六列

c最后输出统计行数

  • 案例2:统计系统中使用bash作为登录Shell的用户总个数

awk 'BEGIN{x=0}/bash$/{x++}END{print x}' /etc/passwd

 a.预处理时赋值变量x=0

b.然后逐行读入/etc/passwd文件,如果发现登录Shell是/bin/bash则x加1

c.全部处理完毕后,输出x的值即可。

3、awk处理条件

  • 正则表达式设置条件

格式:awk [选项]  ‘/正则表达式/{指令}’ 文件名…

包含~   不包含!~

awk -F: '/bash$/{print}' /etc/passwd                                             //输出以bash结尾的行

awk -F: '/root/' /etc/passwd                                                         //执行一个条件{print}可以省略

awk -F: '$1~/root/' /etc/passwd                                                   //输出第1列包含root的行

awk  '/^(127|192)/' /etc/hosts                                                       //输出以127或者192开头的行

awk -F: '$7!~/nologin$/{print $1,$7}' /etc/passwd                       //输出第7列不包含nologin的行的第1、第7列

  • 数值/字符串比较设置条件

等于 ==  不等于!=

大于  >  大于等于 >=

小于  >   小于等于 >=

awk 'NR==2{print}' reg.txt                                                            //输出第2行文本
awk '$2!="XX"{print}' reg.txt                                                        //输出第2列不是XX的行
awk 'NF>=2{print}' reg.txt                                                           //输出包含2个及以上字段的行

 

  • 逻辑测试条件[q1] 

&&  逻辑与:期望多个条件都成立(并且)

||     逻辑或:只要有一个条件成立即满足要求(或者)

awk -F: '$3>1000&&$3<1005' /etc/passwd                                 //找第3列是1001~1004的

awk -F: '$3>=1000&&$3<=1005' /etc/passwd                            // 找第3列是1000~1005的

awk 'NR>=2&&NR<=3' user                                                       //输出第2~3行

awk 'NR<=2&&NR==5' user                                                      //逻辑错误,无输出

awk 'NR<=2||NR==5' user                                                        // 输出1~2行与第5行

awk -F: '$3>10&&$3<20' /etc/passwd                                      // 输出uid大于10小于20的

awk -F: '$3<10||$3>1000' /etc/passwd                                     // 输出uid小于10或者大于1000的

awk -F: '$3<10&&$3>1000' /etc/passwd                                 //无输出(没有小于10又大于1000的数

awk -F: '$3>10&&$3<1000' /etc/passwd                                //输出uid是11~999的

  • 变量的运算

相当于一种运算工具

 + 、- 、* 、/ 、%

  ++ 、-- 、+= 、-= 、*= 、/=

awk 'BEGIN{x++;print x}'                                                               //输出1x默认为0x++1

awk 'BEGIN{print 2+3}'                                                                 // 输出5,相当于计算2+3

seq 30 | awk '$1%3==0'                                                               //找出30以内3的倍数、seq 30 (按行列出显示1-30)

4、awk综合脚本应用

  • 找到使用bash作登录Shell的本地用户、列出这些用户的shadow密码记录

  • 编写脚本的任务要求如下:

分析出使用bash作登录Shell的本地用户

列出这些用户的shadow密码记录

按每行“用户名 -- 密码记录”保存结果

  • 思路:

提取符合条件的账号记录   awk -F:  '/bash$/{print $1}' /etc/passwd

显示用户配置文件第一、第二列  grep "$i:" /etc/shadow |awk -F: '{print $1" --> "$2}'

  • 具体脚本:

#!/bin/bash

u=`awk -F:  ‘/bash${print $1}’  /etc/passwd`

for i  in  $u

do

             grep  “$i:” /etc/shadow | awk -F: ‘{print $1”-->”$2}’                                       //“$i:”加冒号是为了屏蔽再次显示所有

done

4、awk流程控制

  • awk数组 (,可以存储多个值的特殊变量)

定义数组  格式:数组名[下标] =元素值   a[1]=10

调用数组  格式:数组名[下标]           a[1]

遍历数组  用法:for(变量 in 数组名){print 数组名[变量]}

用数组做运算:a[1]=11;a[1]++

 

awk 'BEGIN{a[1]=11;a[2]=22;print a[1]}'                           //定义数组名为a,下标是1,值是11,

awk 'BEGIN{a[1]=11;a[2]=22;print a[2]}'                           //再定义新下标2,值是22,然后输出下标是1的值

awk 'BEGIN{a0++;print a0}'                                              //下标值不定义默认为0

awk 'BEGIN{a[0]++;print a[0]}'                                           //定义下标和值时可以不使用数字

  • for语句

格式:for(变量 in 数组名){print 数组名[变量]}

awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' /var/log/httpd/access_log |sort -nr              //统计网站访问量,并按照降序排列

  • if语句

单分支: if(条件){编辑指令}

双分支: if(条件){编辑指令}else{编辑指令2}

多分支: if(条件){编辑指令}else if{编辑指令2}else if{编辑指令3}…else{编辑指令N}

awk  -F: ‘{if($3<=1000){i++}}END{print i}}’ /etc/passwd                                             //统计/etc/passwd文件中UID小于或等于1000的用户个数

awk  -F: '{if($3<=1000){i++}else{j++}}END{print i,j}'  /etc/passwd                            //分别统计/etc/passwd文件中UID小于或等于1000、UID大于1000的用户个数

awk -F: '{if($7~/bash/){x++}else if($7~/nologin/){y++}else{z++}}END{print x,y,z}' /etc/passwd       //分别统计/etc/passwd文件中登录Shell是“/bin/bash”、 登录Shell是“/bin/nologin”、登录Shell不是“/bin/bash” 也不是“/bin/nologin”的用户个数

  • 扩展:sort 命令

支持常用的排序功能

默认情况下,sort命令,以字母序进行文本排序,再到数字

格式:sort  [ 选项 ] 文件名
                                -n    按字符串数值升序排序
                                -r    降序排序,默认为升序
                                -u    去除重复的行
                                -o    将输出写入文件
                                -k    指定按哪一列排序

5、awk综合案例

  • 案例1:编写监控脚本

            CPU负载
            网卡流量
            内存剩余容量
            磁盘剩余容量
            计算机账户数量
            当前登录账户数量
            计算机当前开启的进程数量
            本机已安装的软件包数量

[root@svr5 ~]# vim test.sh

#!/bin/bash

ip=`ifconfig eth0 | awk '/inet /{print $2}'`

echo "本地IP地址是:"$ip

cpu=`uptime | awk '{print $NF}'`                                                 #awk中NF为当前行的列数,$NF是最后一列

echo "本机CPU最近15分钟的负载是:"$cpu

net_in=`ifconfig eth0 | awk '/RX p/{print $5}'`

echo "入站网卡流量为:"$net_in

net_out=`ifconfig eth0 | awk '/TX p/{print $5}'`

echo "出站网卡流量为:"$net_out

mem=`free | awk '/Mem/{print $4}'`

echo "内存剩余容量为:"$mem

disk=`df | awk '/\/$/{print $4}'`

echo "根分区剩余容量为:"$disk

user=`cat /etc/passwd |wc -l`

echo "本地账户数量为:"$user

login=`who | wc -l`

echo "当前登陆计算机的账户数量为:"$login

process=`ps aux | wc -l`

echo "当前计算机启动的进程数量为:"$process

soft=`rpm -qa | wc -l`

echo "当前计算机已安装的软件数量为:"$soft

 

  • 案例2:编写安全检测脚本

发现登录服务器输入密码错误超过3次时,将信息发邮件给管理员

#!/bin/bash

x=`awk '$0!~/invalid/&&/Failed/{ip[$11]++}END{for(i in ip){print ip[i],i}}' /var/log/secure |awk '{if($1>3){print "目前有主机"$2"尝试登陆服务器,尝试次数为"$1"次"}}'`

[ -z $x ] || echo "$x" |mail -s test root

结束啦
这篇的基本介绍就先写到这里,shell脚本的一些基本知识总结到这,后面会继续更新shell脚本的一些常用的用法以及企业中一些实用的shell脚本的运用,感谢你们的浏览,也希望对你们有所帮助,你的点赞是我努力的动力,谢谢你们!

 

 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值