shell编程三剑客

  1. grep --> egrep --> 文本过滤 查询
  2. awk 文本截取
  3. sed  文本的替换和修改

目录

awk

awk也可以做小数运算

awk命令简要处理流程

awk的数据字段变量

awk命令的基本语法

awk基本命令示例

awk用 -F 来指定分隔符separater、delimiter

awk命令的完整语法

awk命令的执行过程

awk命令的操作符

awk命令的引用shell变量

awk里的变量的传递问题和shell脚本的传参问题

练习:

经典面试题


awk

  • awk 是一门模式扫描和处理的语言 --> 专门进行文本截取和分析的工具
  • 支持流控、正则
  • gawk - pattern scanning and processing language

awk也可以做小数运算

awk命令简要处理流程

awk的数据字段变量

  • $0 表示整行文本
  • $1 表示文本中第一个数据字段
  • $2 表示文本中第二个数据字段
  • $n 表示文本中第n个数据字段

awk命令的基本语法

  • awk的指令一定要用单引号引起,动作一定要用花括号括起
  • 模式可以是正则表达式、条件表达式或两种组合
    • 如果模式是正则表达式要用/定界符
  • 多个动作之间用;分开
  • 引用自定义变量,不需要接$符号

awk基本命令示例

# 只有模式没有动作,结果和grep一样,显示$0
awk '/bash/' /etc/passwd# 只有动作没有模式,就直接执行动作
who | awk '{print $2}'# 以冒号为分隔符,显示以h开头的行的第一列和第七列
awk -F: '/^h/{print $1,$7}' /etc/passwd# 不显示以a或b或c开头的行的第一列和第七列
# [^ ] 中括号里面的^表示取反,'^[^ ]'中括号外面的^表示以中括号里面的内容开头
awk -F: '/^[^abc]/{print $1,$7}' /etc/passwd# 以 : 或者 / 作为分隔符显示第1列和第10列
awk -F '[:/]' '{print $1,$10}' /etc/passwd

awk -F 来指定分隔符separaterdelimiter

  • 默认的字段分隔符是任意空白字符(空格或者TAB)
  • 输入分隔符 FS = filed separater
  • 输出分隔符 OFS = output filed separate
  • [root@kafka01 yum.repos.d]# awk -F: '{print $1,$3,$5}' /etc/passwd
    • 输入分隔符是冒号 输出分隔符默认为空格
  • [root@kafka01 yum.repos.d]# awk -F: 'OFS="#"{print $1,$3,$5}' /etc/passwd
    • 指定输出符为 # 号
    • ,  逗号其实就是在调用输出分隔符
  • [root@kafka01 ~]# awk -F: 'OFS=","{print $1,$3,$5}' /etc/passwd  > passwd.csv
    • 方便重定向为csv文件
  • [root@kafka01 yum.repos.d]# awk -F: '{print $1" "$3"#"$5}' /etc/passwd
    • 自己加分隔符

awk命令的完整语法

awk命令的执行过程

  • 先执行BEGIN{commands}语句块中的语句
  • 从文件或 stdin 中读取第1行,
  • 查看有无模式匹配(/bash/ 找有bash的行), 若无则匹配下一行,如果每行都不匹配就执行END{}中的语句
  • 若有则检查该整行与pattern是否匹配, 若匹配, 则执行{}中的语句,若不匹配则不执行{}中的语句,接着读取下一行
  • 重复这个过程, 直到所有行被读取完毕
  • 执行END{commands}语句块中的语句
  • 文字太繁琐!举例就懂啦!
[root@kafka01 1-6]# awk -F: 'BEGIN{print "~~~start~~~"} /bash/{print $1,$3} END{print "~~~end~~~"}' /etc/passwd
~~~start~~~
root 0
~~~end~~~
[root@kafka01 1-6]# awk -F: 'BEGIN{print "~~~start~~~"} /bash$/{print $1,$3} END{print "~~~end~~~"}' /etc/passwd
~~~start~~~
root 0
~~~end~~~
[root@kafka01 1-6]# awk -F: 'BEGIN{print "~~~start~~~"} /^zabbix/{print $1,$3} END{print "~~~end~~~"}' /etc/passwd
~~~start~~~
zabbix 992
~~~end~~~

pattern部分每行都执行(可以使用正则),BEGIN、END部分只执行一次

[root@kafka01 1-6]# awk 'BEGIN{i=0}{i++}END{print i}' /etc/passwd # 统计文件行数[root@kafka01 1-6]# awk -F: '{print $1,NR}' /etc/passwd  NR可以直接显示行号
  • NR:number of record 显示行号 (常用!很方便!很重要!)
  • NF:number of filed 统计一行里字段数
# 显示用户名,行号和最后一个字段
[root@kafka01 1-6]# awk -F: '{print $1,NR,$NF}' /etc/passwd
# 显示用户名,行号和倒数第二个字段
[root@kafka01 1-6]# awk -F: '{print $1,NR,$(NF-1)}' /etc/passwd
# 显示3到5行
[root@kafka01 1-6]# awk 'NR==3,NR==5{print NR,$0}' /etc/passwd
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
# 显示行号大于2的 (只显示df -h结果的第一列文件系统)
[root@kafka01 1-6]# df -Th|awk 'NR>=2 {print $1}'
  • $NF 取最后一个字段

awk命令的操作符

数学运算:+,-,*,/, %,++,- -

逻辑关系符:&&, ||, !

  • && 比 || 的优先级要高

比较操作符:>,<,>=,!=,<=,==,~,!~

文本数据表达式:== (精确匹配)

~ 波浪号表示匹配后面的模式(模糊匹配)

如:

[root@kafka01 1-6]# who | awk '$2 ~ /pts/{print $1}'[root@kafka01 1-6]# awk -F: '$3 ~ /\<...\>/ {print $1,$3}' /etc/passwd
  • \<    单词的界定符  单词以什么什么开头
  • \>    表示单词以什么什么结尾
  • .  点表示单个任意字符

[root@kafka01 1-6]# awk -F: '$3 ~ /[0-9]{3}/ {print $1,$3}' /etc/passwd

[root@kafka01 1-6]# awk -F: '$3 ~ /\<[0-9]{3}\>/ {print $1,$3}' /etc/passwd

[root@kafka01 1-6]# cat mobile_phone.txt | grep "\<feng"

VIVO OPPO 12345 feng@qq.com

[root@kafka01 1-6]# cat mobile_phone.txt | grep "mi\>"

xiaomi huawei XIAOMI HUAWEI

xiaomi dami

正则还支持

\bwubing\b

界定单词,只是查找wubing单词,包含wubing的不算

\bwubing

单词以wubing开头

wubing\b

单词以wubing结尾

\<wubing\>

定界单词,只是查找wubing单词,包含wubing的不算

\babc\b等于\<abc\>
举例(学了以上知识,要看懂以下语句喔)
[root@kafka01 1-6]# seq 100 | awk '$1 % 5 == 0 || $1 ~ /^1/ {print $1}'[root@kafka01 1-6]# awk -F: ' $1 == "root" {print $1,$3}' /etc/passwd[root@kafka01 1-6]# ps aux | awk '$2 <=10 {print $11}' PID号小于10的命令

awk命令的引用shell变量

-v 引入shell变量

[root@kafka01 1-6]# name="lmy"
[root@kafka01 1-6]# echo | awk -v  new_name=$name '{print new_name}'
lmy

-v 常用在写脚本中,比如我们把某个东西得到了,要通过它来截取一段文字或其他操作

[root@kafka01 1-6]# cat user.sh
read -p "please input your name:" u_name
echo |awk -v new_name=$u_name -F: '$1 == new_name {print $1,$3}' /etc/passwd
[root@kafka01 1-6]# bash user.sh
please input your name:zabbix
zabbix 992

不使用-v选项,直接使用shell里的变量,需要使用双引号,{}括号里的$符号需要转义,举例如下:

[root@kafka01 1-6]# abc=pcp
[root@kafka01 1-6]# awk -F: "/^$abc/{print NR,\$0}" /etc/passwd
28 pcp:x:993:988:Performance Co-Pilot:/var/lib/pcp:/sbin/nologin[root@kafka01 1-6]# name=zabbix
[root@kafka01 1-6]# awk -F: "\$1~ /$name/ {print \$1,\$3}" /etc/passwd
zabbix 992

也可以使用单引号,将变量引起来,然后前面加一个$符号再次引用变量的值,相当于取2次值

[root@kafka01 1-6]# sg=3
[root@kafka01 1-6]# awk -F: '/root/{print $1,$'$sg'}' /etc/passwd
root 0
operator 11

总结一下:

awk里的变量的传递问题和shell脚本的传参问题

可以在BEGIN部分定义,整个处理的过程都可以使用,END部分也可以使用

cat /etc/passwd|awk 'BEGIN{OFS="####";FS=":"}{print $1,$3}'

往脚本里传递参数:

  • read -p
  • 位置变量

shell里的变量传递到awk里的问题?

  1. awk -v
  2. 或者使用双引号
  3. BEGIN部分定义
  4. 使用单引号

练习:

1. 统计名字里包含a字母用户的数量,输出用户名

awk -F: 'BEGIN{i=0} $1 ~/a/ {i++;print $1,i}END{print i}' /etc/passwdawk -F: 'BEGIN{i=0}{if ($1 ~/a/)print$1,i++}END{print i}' /etc/passwd

2. 统计/etc/passwd文件里的使用bash的用户的个数,并且还要显示出来这些行

awk -F: 'BEGIN{i=0} $NF ~ /bash/{i++;print $1,i}END{print i}' /etc/passwd

3. 取出ip地址

[root@kafka01 ~]# ip add| awk '/inet.*ens33/{print $2}'
[root@kafka01 ~]# ip add| awk '$NF ~ /ens33/{print $2}'

4.使用ifconfig,使用awk显示eth0的入站流量和出站流量(字节)

[root@kafka01 ~]# ifconfig ens33|awk 'NR==5||NR==7{print $5}'
[root@kafka01 ~]# ifconfig ens33|awk '$0 ~ /RX.*bytes|TX .*bytes/{print $5}'

统计每秒钟ens33网卡的接受和发送数据的流量(编写脚本或使用watch命令)

watch -n 1 -d "ifconfig ens33|awk 'NR==5||NR==7{print $5}'"

5.使用awk命令统计以r开头的用户数目,显示如下效果

[root@kafka01 ~]# cat /etc/passwd|awk -F: 'BEGIN{i=0}$1 ~ /^r/{print $1;i++}END{print i}'

6. 判断系统里哪些用户没有设置密码或者密码为空的用户,输出这些用户的名字,并且统计没有设置密码的用户个数。

提示:

  • 密码字段为*、!!表示没有设置密码
  • 密码字段为空说明密码被清除
[root@kafka01 1-6awk]# awk -F: 'BENGIN{i=0}length($2)<=2{print $1,"user not set password";i++}END{print i}'  /etc/shadow

经典面试题

1.如果有一列数字,怎么加起来

[root@kafka01 1-6]# cat number.txt
1
2
3
4
5
[root@kafka01 1-6]# cat number.txt |awk 'BEGIN{i=0}{i+=$0}END{print i}'
15

2.检查/var/log/secure日志文件,如果有主机用root用户连接服务器的ssh服务失败次数超过10次(10次必须使用变量),就将这个IP地址加入/etc/hosts.deny文件(或者使用iptables)拒绝其访问,如果这个IP已经存在(已经存在在iptables链里了)就无需重复添加到/etc/hosts.deny文件

[root@kafka01 1-6awk]# cat ssh_secure.sh
#!/bin/bash# 检查/var/log/secure日志文件,如果有主机用root用户连接服务器的ssh服务失败次数超过3次(3次必须使用变量),就将这个IP使用iptables拒绝其访问,如果这个IP已经存在iptables链里了,就无需重复添加# 得到登录失败次数大于3的主机ip地址
failed_host=$(cat /var/log/secure |awk '$0 ~ /Failed/{print $(NF-3)}'|sort|uniq -c|awk '$1>2{print $2}')# 得到iptables中的ssh服务拦截主机ip
exist_host=$(iptables -L INPUT -n |egrep '22\>' |awk '{print $4}')# 将不在ssh拦截的主机添加进iptables
for i in $failed_host
doif ! echo $exist_host|egrep $itheniptables -A INPUT -s $i -p tcp --dport 22 -j DROPfi
done

需求分析:
  1.这个脚本需要一直执行
  2.查看/var/log/secure文件,统计出Failed password行的ip地址,一旦这个ip地址连接的次数超过10,就将这个ip地址加入黑名单/etc/hosts.deny
  3.sshd:172.16.145.128   追加到/etc/hosts.deny文件里

#!/bin/bashawk '$0~/Failed/{print   $11}' /var/log/secure|sort|uniq -c|awk '{print $1,$2}' >sshd.txt
ip_addr=($(awk '{print $2}' sshd.txt))
ip_num=($(awk '{print $1}' sshd.txt))for i in ${!ip_addr[@]}
doif egrep "${ip_addr[i]}" /etc/hosts.deny &>/dev/nullthenecho "${ip_addr[i]} aready exists"echo "${ip_addr[i]}" have access ${ip_num[i]} times elseecho "################################"((${ip_num[i]} >10 ))&&echo "sshd:${ip_addr[i]}" >>/etc/hosts.denyecho "${ip_addr[i]}" have access ${ip_num[i]} times fi  donewhile true
doIP_list=($(cat /var/log/secure|awk '{print $6,$11}'|egrep '^Failed'|sort|uniq -c|awk '{if($1>10) print $3}'))for i in ${!IP_list[@]}doif cat /etc/hosts.deny|egrep "${IP_list[i]}" &>/dev/nullthen:elsesed -i  "$ a sshd:${IP_list[i]}:deny" /etc/hosts.denyfidone
sleep 5
done

下一篇还会继续探讨awk中支持的函数和结构化语句!我们下篇见!

Linux文本三剑客之一——awk详解(1)——awk看这两篇就够啦~PS:文末有练习,来练练手吧相关推荐

  1. 详解Seaborn,看这一篇就够了

    转载:Seaborn常见绘图总结 Seaborn是一个比Matplotlib集成度更高的绘图库,在科研和数据分析中我们常常看到一些画的非常高大上的图,这往往就是Seaborn绘制的图形.因此我们就使用 ...

  2. Linux文本编译工具VIM详解

    Linux文本编译工具VIM详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.VIM概述 1>.vim简介 1>.vi: 全称Visual editor,即文本编 ...

  3. CompletableFuture使用详解(全网看这一篇就行)

    Java8 CompletableFuture 用法全解_孙大圣666的博客-CSDN博客_completablefuture ​​​CompletableFuture使用详解(全网看这一篇就行)_代 ...

  4. php 字符流在linux,PHP_linux正则表达式awk详解,awk和sed一样是流式编辑器,它 - phpStudy...

    linux正则表达式awk详解 awk和sed一样是流式编辑器,它也是针对文档中的行来操作的,一行一行的去执行.awk比sed更加强大,它能做到sed能做到的,同样也能做到sed不能做到的.awk常用 ...

  5. awk详解:awk语言及应用

    是时候归纳一下awk命令了. awk是三个人名的缩写,他们是:Aho.(Peter)Weinberg和(Brain)Kernighan.正是这三个人创造了awk-一个优秀的样式扫描与处理工具. 作为l ...

  6. Dubbo详解,用心看这一篇文章就够了【重点】

    1.1 Dubbo概述 Dubbo是阿里巴巴开源的基于 Java 的高性能RPC(一种远程调用) 分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案. 每天为2千 ...

  7. DFS (深度优先搜索) 算法详解 + 模板 + 例题,这一篇就够了

    深度优先搜索算法(Depth First Search,简称DFS):一种用于遍历或搜索树或图的算法. 沿着树的深度遍历树的节点,尽可能深的搜索树的分支.当节点v的所在边都己被探寻过或者在搜寻时结点不 ...

  8. Linux_进程管理详解《鸟哥的Linux私房菜》学习笔记(极其详细,看完这篇就够了)

    前言 当一个程序被载入到内存中运行,那么在内存中的那个程序就被称为进程(process).进程是操作系统上非常重要的概念, 所有系统上面跑的数据都会以进程的形态存在. 那么系统的进程有哪些状态?不同的 ...

  9. 详解电池管理系统,这一篇就够了!

    BMS电池管理系统(BATTERY MANAGEMENT SYSTEM)俗称电池管家,主要就是为了智能化管理及维护各个电池单元,防止电池出现过充.过放.过流等情况,延长电池的使用寿命,监控电池的状态. ...

最新文章

  1. 在jupyter notebook中同时安装python2和python3
  2. 令人头疼的clientTop、scrollTop、offsetTop
  3. Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
  4. Boost:基于不同容器的有界缓冲区比较
  5. 任务调度之Quartz2
  6. Codechef REBXOR HYSBZ - 4260(01字典树+区间异或最大)
  7. 升降压斩波电路matlab,升降压斩波电路的MATLAB 仿真.pptx
  8. python扫雷脚本_Python自动扫雷实现方法
  9. 浅析Java的线程和Golang的协程
  10. 通过云打码实现人人网模拟登陆(现在已经无法使用)
  11. linux服务器无法解析域名解决办法,Linux服务器内部无法解析域名
  12. C# Excel插入Object
  13. 跳过 Windows 11 的联网的方法
  14. 基于人工智能深度学习和经典算法的药物设计软件MolAICal
  15. Facial Expression Recognition based on a multi-task global-local network--论文笔记
  16. 一切照旧... ...
  17. tomcat配置前端静态文件gzip压缩
  18. 4.2 线性方程组有解判断
  19. win10卸载程序时提示找不到xxx.msi文件
  20. Python报错:'dict' object has no attribute 'iteritems' 的解决方案

热门文章

  1. mysql mmm 虚拟ip不通_mysql-mmm故障解决一例
  2. Error - 使用statsmodels报错ModuleNotFoundError: No module named 'pandas.tseries.tools'
  3. JSP学习并实现的过程--day01
  4. 经典龙格-库塔法(四阶龙格-库塔法)求解求一阶常微分方程相应的特解的Python程序
  5. 网页从输入url到呈现页面流程
  6. java 批次号,java重复批次执行
  7. java 支付宝退款批次号生成
  8. 中国工业制造RFID市场竞争力排名分析与投资战略规划研究报告2022-2028年版
  9. 普通话计算机辅助测试作品5号,普通话测试朗读作品范文《作品5号》
  10. 江苏高等学校计算机等级考试大纲与样卷,江苏省高等学校计算机等级考试大纲(2015 年修订).pdf...