当前位置: 首页 > news >正文

19 Shell Script awk命令

Shell Script awk命令

一、awk

一)awk介绍

​ awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

​ awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk

​ awk语言的最基本功能是在文件或字符串中基于指定规则来分解抽取信息,也可以基于指定的规则来输出数据

二)awk三种调用方式

​ 命令执行方式:awk [opion] ‘awk_script’ input_file1 [input_file2 …]

​ 将awk_script放入脚本文件并以#!/bin/awk -f 作为首行,给予该脚本可执行权限,然后在shell下通过键入该脚本的脚本名调用之

​ 将所有的awk_script插入一个单独脚本文件,然后调用: awk -f awk脚本文件input_file(s)

三)awk_opion

​ awk [opion] ‘awk_script’ input_file1 [input_file2 …]

​ awk的常用选项option有:

​ -F fs : 使用fs作为输入记录的字段分隔符,如果省略该选项,awk使用环境变量IFS的值

​ -f filename : 从文件filename中读取awk_script

​ -v var=value : 为awk_script设置变量

四)awk_script

​ awk [opion] 'awk_script’input_file1 [input_file2 …]

​ awk_script可以由一条或多条awk_cmd组成,可以有多个awk_cmd

​ awk_cmd由两部分组成: awk_pattern { actions }

​ awk_script可以被分成多行书写,必须确保整个awk_script被单引号括起来

五)awk入门简单案例

1.案例1

​ 显示当前操作系统最近登录的5个IP地址和用户

[root@localhost ~]# last -n 5
root     pts/0        192.168.100.1    Mon Oct 14 07:22   still logged in   
root     tty1                          Mon Oct 14 07:21   still logged in   
reboot   system boot  3.10.0-1160.118. Mon Oct 14 07:19 - 07:22  (00:02)    
root     pts/0        192.168.100.1    Sat Oct  5 01:51 - crash (9+05:28)   
root     tty1                          Sat Oct  5 01:35 - crash (9+05:44)   [root@localhost ~]# last -n 5 | awk '{print $1","$3}'
root,192.168.100.1
root,Mon
reboot,boot
root,192.168.100.1
root,Sat

​ awk工作流程是这样的:读入有’\n’换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域, 1 表示第一个域 , 1表示第一个域, 1表示第一个域,n表示第n个域。默认域分隔符是"空白键" 或"[tab]键",所以$1表示登录用户,$3表示登录用户ip,以此类推。

2.案例2

​ 显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割。

[root@localhost ~]# awk -F: '{print $1,$7}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
……

​ 在上面的基础上添加列名name 和shell,在最后一行添加“end"。

[root@localhost ~]# awk -F: 'BEGIN {print "name\tshell"} {print $1","$7} END {print "end"}' /etc/passwd
name	shell
root,/bin/bash
bin,/sbin/nologin
daemon,/sbin/nologin
adm,/sbin/nologin
lp,/sbin/nologin
sync,/bin/sync
shutdown,/sbin/shutdown
halt,/sbin/halt
mail,/sbin/nologin
……
end

六)awk命令的一般形式

awk -F ' BEGIN { actions }awk_pattern1 { actions ............awk_patternN { actions }END { actions }
' inputfile

​ 其中BEGIN { actions } 和END { actions } 是可选的

七)awk的运行过程

​ 1.如果BEGIN 区块存在,awk执行它指定的actions

​ 2.awk从输入文件中读取一行,称为一条输入记录(如果输入文件省略,将从标准输入读取)

​ 3.awk将读入的记录分割成字段,将第1个字段放入变量$1中,第2个字段放入$2,以此类推。$0表示整条记录。字段分隔符使用shell环境变量IFS或由参数指定

​ 4.把当前输入记录依次与每一个awk_cmd中awk_pattern比较,看是否匹配,如果相匹配,就执行对应的actions。如果不匹配,就跳过对应的actions,直到比较完所有的awk_cmd

​ 5.当一条输入记录匹配所有的awk_cmd后,awk读取输入的下一行,继续重复步骤3和4,这个过程一直持续,直到awk读取到文件尾

​ 6.当awk读完所有的输入行后,如果存在END,就执行相应的actions。

八)awk的语法规则总结

​ iput_file可以是多于一个文件的文件列表,awk将按顺序处理列表中的每个文件

​ 一条awk_cmd的awk_pattern可以省略,省略时不对输入记录进行匹配比较就执行相应的actions

​ 一条awk_cmd的actions 也可以省略,省略时默认的动作为打印当前输入记录(print $0)

​ 一条awk_cmd中的awk_pattern和actions不能同时省略

​ BEGIN区块和END区块分别位于awk_script的开头和结尾

​ awk_script中只有END区块或者只有BEGIN区块是被允许的

​ 如果awk_script中只有BEGIN { actions } ,awk不会读取input_file

​ awk把输入文件的数据读入内存,然后操作内存中的输入数据副本,awk不会修改输入文件的内容

​ awk的总是输出到标准输出,如果想让awk输出到文件,可以使用重定向

二、awk高级部分

一)awk_pattern的几种类型

​ awk_pattern { actions }

​ awk_pattern模式部分决定actions动作部分何时触发及触发actions

​ 正则表达式用作awk_pattern

​ 布尔表达式用作awk_pattern

​ 逻辑操作符组合awk_pattern

​ 逗号分隔的两个正则表达式,表示选择范围

​ 正则表达式用作awk_pattern: /regexp/

​ awk中正则表达式匹配操作中经常用到的字符

​ ^ $ . [] | () * // 通用的regexp元字符

​ + : 匹配其前的单个字符一次以上,是awk自有的元字符,不适用于grep或sed等

​ ? : 匹配其前的单个字符1次或0次,是awk自有的元字符,不适用于grep或sed等

​ 查找所有zabbix用户的进程和进程PID

[root@localhost ~]# ps -ef | awk '/^zabbix/ {print $1,$2}'
zabbix 1024
zabbix 1028
zabbix 1029
zabbix 1030
zabbix 1031
zabbix 1032

​ 布尔表达式用作awk_pattern,表达式成立时,触发相应的actions执行

​ 表达式中可以使用变量(如字段变量$1,$2等)和/regexp/

​ 布尔表达式中的操作符

​ 关系操作符: < > <= >= == !=

​ 匹配操作符:

​ value ~ /regexp/ 如果value匹配/regexp/,则返回真

​ value !~ /regexp/ 如果value不匹配/regexp/,则返回真。

​ awk’$2 > 10 {print “ok”}’ input_file

​ awk’$3 ~ /^d/ {print “ok”}’ input_file

[root@localhost ~]# ps -ef | awk '$2 > 1400 {print $1,$2}' 
UID PID
root 1404
root 1437
root 1464
root 1471
root 1484
root 1485

​ 逻辑操作符组合awk_pattern

​ &&(与) 和||(或) 可以连接两个/regexp/或者布尔表达式,构成混合表达式

​ !(非) 可以用于布尔表达式或者/regexp/之前

​ awk ‘($1 < 10 ) && ($2 > 10) {print “ok”}’ input_file

​ awk ‘/^d/ || /x$/ {print “ok”}’ input_file

[root@localhost ~]# ps -ef | awk '($2 > 1000) && ($2 < 1100) {print $1,$2}'
root 1017
root 1019
root 1020
zabbix 1024
zabbix 1028
zabbix 1029
zabbix 1030
zabbix 1031
zabbix 1032

二)awk高级特性

1.awk支持与特性

​ awk支持内置变量:

​ ARGC 命令行参数个数

​ ARGV 命令行参数排列

​ ENVIRON 支持队列中系统环境变量的使用

​ FILENAME awk浏览的文件名

​ FNR 浏览文件的记录数

​ FS 设置输入域分隔符,等价于命令行F选项

NF 浏览记录的域的个数

NR 已读的记录数

​ OFS 输出域分隔符

​ ORS 输出记录分隔符

​ RS 控制记录分隔符

# NR的使用
[root@localhost ~]# awk -F: '{print NR,$1, $7}' /etc/passwd
1 root /bin/bash
2 bin /sbin/nologin
3 daemon /sbin/nologin
4 adm /sbin/nologin
5 lp /sbin/nologin
6 sync /bin/sync
7 shutdown /sbin/shutdown
8 halt /sbin/halt
9 mail /sbin/nologin
……

​ 支持函数

​ print、split、substr、sub、gsub

# split切割字符串
[root@localhost ~]# echo "today is 2024-01-01" | awk '{split($3,my_arr,"-");print my_arr[2]}'
01

​ 支持流程控制语句,类C语言

​ if、while、do/while、for、break、continue

​ 支持自定义变量,数组

​ a[1] a[tom] map(key)

2.awk高级案例

​ 搜索/etc/passwd有root关键字的所有行

[root@localhost ~]# awk '/root/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

​ 统计/etc/passwd文件中账户人数

[root@localhost ~]# awk '{count++} END {print "用户数量:", count}' /etc/passwd
用户数量: 26

​ 使用for循环显示/etc/passwd的所有账户。显示格式:序号 账户名

# 直接输出
[root@localhost ~]# awk -F: 'BEGIN {i=0;} {users[i]=$1;i++} END {for(n in users){print n,users[n]}}' /etc/passwd
17 sshd
4 lp
18 postfix
5 sync
19 chrony
6 shutdown
7 halt
8 mail
9 operator
10 games
20 apache
……# 按顺序输出
[root@localhost ~]# awk -F: 'BEGIN {count=0;} {users[count]=$1;count++} END {for(i = 0;i<count;i++){print i,users[i]}}' /etc/passwd                                                                             
0 root
1 bin
2 daemon
3 adm
4 lp
5 sync
6 shutdown
7 halt
8 mail
……

三、awk综合案例

​ 统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹)

[root@localhost ~]# ls -l /etc/ | awk 'BEGIN {sum=0;print "统计/etc下的文件总大小";} {if($5 !=4096){sum+=$5}} END {print "总大小为:",sum/1024/1024,"M"}'
统计/etc下的文件总大小
总大小为: 0.903872 M

​ 统计报表:

​ 合计每人1月工资

​ 员工角色码值:0:manager,1:worker

​ Tom 0 2012-12-11 car 3000

​ John1 2013-01-13 bike 1000

​ vivi1 2013-01-18 car 2800

​ Tom0 2013-01-20 car 2500

​ John1 2013-01-28 bike 3500

[root@localhost ~]# cat user.txt
Tom      0   2012-12-11     car     3000
John     1   2013-01-13     bike    1000
vivi     1   2013-01-18     car     2800
Tom      0   2013-01-20     car     2500
John     1   2013-02-28     bike    3500# 编写awk脚本
[root@localhost ~]# vi awk.my    
#!/bin/awk -f
BEGIN {print "姓名\t工资\t角色";i=0;
}
{split($3,date,"-");if(date[2]=="01"){name[i]=$1;sal[i]=$5;if($2==0){role[i]="经理";}else{role[i]="普通员工";}}i++;
}
END {for(n=0;n<i;n++){print name[n]"\t"sal[n]"\t"role[n];}
}# 添加可执行权限
[root@localhost ~]# chmod 755 awk.my# 执行脚本
[root@localhost ~]# ./awk.my user.txt
姓名	   工资	 角色
John	1000	普通员工
vivi	2800	普通员工
Tom     2500	经理

http://www.mrgr.cn/news/50387.html

相关文章:

  • 华为OD机试真题---热点网站统计
  • C# Attribute 介绍
  • 大模型应用开发过程中主流架构模式——大模型+多个小模型
  • Windows 11开发
  • DDR系列之一: 内存的种类
  • 【前端】浏览器中的hevc视频播放库汇总,无需wasm
  • 扩散模型训练方法一直错了!
  • 计算机和网络
  • Redis拒绝连接问题分析与解决方案
  • 黑龙江等保测评:APP安全性的重要性与实施策略
  • XPM_CDC_ARRAY_SINGLE
  • Java比较两个Excel是否内容一致
  • 【接口限流】java中springboot实现接口限流防抖处理(JUC注解版)
  • 【Java小白系列课】-01-Java环境安装-变量
  • Palo Alto Networks Expedition 未授权SQL注入漏洞复现(CVE-2024-9465)
  • 网络资源模板--Android Studio 实现宿舍管理系统App
  • MYSQL数据库和oracle数据库的详细对比,该怎么选择?
  • ICM20948 DMP代码详解(81)
  • pandas中数据子集的获取
  • 惊人秘诀!揭秘ChatGPT写作的最佳提问技巧!帮你拿到满分论文