文本三剑客——awk 截取+过滤+统计(1)+https://developer.aliyun.com/article/1557885
五、awk命令的操作符
1、awk中的操作符
~:模糊匹配
~/ /:模糊匹配
//里面写查找的内容
~ /\<luoziyao$\>/:其中$表示以什么结束。
[root@localhost shell]# awk -F: '$1 ~ /\<luoziyao$\>/{print $1,$3}' /etc/passwd luoziyao 2021
其中NR==1表示第一行。
[root@localhost shell]# awk 'NR==1{print NR,$0}END{print NR,$0}' /etc/passwd 1 root:x:0:0:root:/root:/bin/bash 88 luoziyao1:x:2022:2025::/home/luoziyao1:/bin/bash
n, --interval seconds: 指定间隔时间。Specify update interval. The command will not allow
-d, --differences [permanent]:以高亮显示。Highlight the differences between successive update
[root@localhost shell]# watch -n 2 -d "ifconfig|awk 'NR==5{print $5}'" watch -n 2 -d " ifconfig |egrep -A8 "^ens33"|awk '/RX p/||/TX p/{print \$5}'"
2、shell里的变量在awk里传递参数的问题
①echo $$:查看当前进程(bash)的进程号。
[root@localhost ~]# echo $$ 7894
②PROCINFO:是awk的内置数组,用来存储进程的相关信息。
root@localhost ~]# awk '{print PROCINFO["pid"],PROCINFO["ppid"]}' /etc/passwd 10940 10923 10940 10923 10940 10923
③在shell中引用变量。
\$1:需要进行转义,在awk中,引用shell变量时不需要进行转义,需要加$符号:$s来引用变量,但是位置变量需要进行转义:如:\$1.
[root@localhost ~]# sg=renhaodong [root@localhost ~]# awk -F: "/$sg/{print \$1}" /etc/passwd renhaodong
④流控:following control。
if:if(condition )statement
单分支:
[root@localhost ~]# awk -F: '{if($1 ~ /renhaodong/) print "haoge"}' /etc/passwd haoge [root@localhost ~]# awk -F: '{if($1 ~ /renhaodong/) print "haoge";else print "dage"}' /etc/passwd dage dage dage dage
多分支:
root@localhost ~]# awk -F: '{if($1 ~ /renhaodong/) print "haoge";else if($3>5000)print "dageda"; print "dage"}' /etc/passwd dage dage dage dage
小练习:①、将/etc/passwd下uid=0为超级用户,大于1并且小于等于999的为系统用户,大于1000的为普通用户。
[root@localhost ~]# awk -F: '{if($3==0) print "超级用户";else if($3>1&&$3<100)print " 系统用户"; print "普通用户"}' /etc/passwd 超级用户 系统用户 系统用户 系统用户 系统用户 系统用户 系统用户
②、简单版:
[root@localhost ~]# awk -F: 'BEGIN {num=0;num2=0;num3=0}{if($3==0)num++;else if ($3>1&&$3<1000)num2++;else num3++}END{print "超级用户的数量:"num",系统用户的数量:"num2",普通.户的数量:"num3""}' /etc/passwd 超级用户的数量:1,系统用户的数量:26,普通用户的数量:62 [root@localhost ~]# awk -F: '{if($3==0)num++;else if ($3>1&&$3<1000)num2++;else num3++}END{print "超级用户的数量:"num",系统用户的数量:"num2",普通用户的数量:"num3""}' /etc/passwd 超级用户的数量:1,系统用户的数量:25,普通用户的数量:63 [root@localhost ~]# awk -F: '{if($3==0){num++;print $3,$1"是超级用户"}else if ($3>1&&$3<1000)num2++;else num3++}END{print "超级用户的数量:"num",系统用户的数量:"num2",普通用户 的数量:"nm3""}' /etc/passwd 0 root是超级用户 超级用户的数量:1,系统用户的数量:25,普通用户的数量:63
升级版:
[root@localhost ~]# awk -F: 'BEGIN{num1=0;num2=0;num3=0}{if ($3 == 0) {num1++;print "超级用户"}else if ($3>=1&&$3<=999) {num2++;print "系统用户"}else {num3++;print "普通用户"}}END{print "一共有超级用 户:"num1,"一共有系统用户:"num2,"一共 普通用户:"num3}' /etc/passwd 普通用户 普通用户 普通用户 普通用户 普通用户 普通用户 ...... 一共有超级用户:1 一共有系统用户:26 一共 普通用户:62
3、awk的for循环格式
for (i=0;i<10;i++) {print $i;}
for (i in array) {print array[i]} --->直接从数组的下标里读一个值,取完所有的值,遍历。
python里字典 key:value
练习:
[root@localhost ~]# awk -F: '{split($6,home_dir,"/")}END{for (i in home_dir)print i,home[i]}' /etc/passwd 1 2 3 [root@localhost ~]# awk -F: '{split($6,home_dir,"/")}END{for (i in home_dir)print i,home_dir[i]}' /etc/passwd 1 2 home 3 renhaodong [root@localhost ~]# awk -F: '{split($6,home_dir,"/");for (i=2;i<4;i++) print i,home_dir[i]}' /etc/passwd 2 root 3 2 bin 3 2 sbin .... [root@localhost ~]# awk -F: '{split($6,home_dir,"/");for (i in home_dir) print i,home_dir[i]}' /etc/passwd 1 2 root 1 2 bin 1 ......
4、 awk中的函数
①length:统计长度
[root@localhost ~]# awk -F: 'length($1) >6 {print $1}' /etc/passwd|head
②split:将一段字符串根据根据分隔符号,对文本进行分割,存放到数组里,使用for循环取遍历读取数组里的内容。
[root@localhost ~]# awk -F: '{ if (length($1) >6) print substr($1,3,6)}' /etc/passwd|head utdown erator stemd- [root@localhost ~]# python Python 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> sg = "wangshuai wangzixiang mahaoliang tanghaoming zengkaijie" >>> sgs = sg.split() >>> sgs ['wangshuai', 'wangzixiang', 'mahaoliang', 'tanghaoming', 'zengkaijie'] >>> mn = "aojiao/xieshan/tanxue/shiyuqian/chenyulin/luo" >>> mns = mn.split("/") >>> mns ['aojiao', 'xieshan', 'tanxue', 'shiyuqian', 'chenyulin', 'luo']
③gsub:替换
substr: 截取部分字符串
例如:截取$1中长度大于6的。
[root@localhost ~]# awk -F: '{ if (length($1) >6 ) print $1}' /etc/passwd |head shutdown operator systemd-network .......... [root@localhost ~]# awk -F: '{ if (length($1) >6 ) print substr($1,1)}' /etc/passwd |head shutdown operator systemd-network ........ 如果$1的长度大于6,从第一个开始截取6个 [root@localhost ~]# awk -F: '{ if (length($1) >6) print substr($1,1,6)}' /etc/passwd|head shutdo operat system polkit postfi .......
④ toupper:转换成大写
[root@localhost ~]# awk -F: '{print toupper($1)}' /etc/passwd ROOT BIN DAEMON ADM LP SYNC SHUTDOWN
⑤ tolower:转换成小写
[root@localhost ~]# awk -F: '{print tolower($1)}' /etc/passwd
5、awk中的单个创建
①、创建用户:useradd
[root@localhost shell]# awk '{system("useradd " $1)}' name.txt useradd:用户“yuanrundong”已存在 useradd:用户“hepang”已存在 useradd:用户“shiyuqian”已存在 useradd:用户“tanxue”已存在
②、根据一个文件里的内容,批量新建用户和设置密码
第一种:awk指令进行创建。
[root@localhost shell]# awk '{system ("useradd "$2);system("echo "$3"|passwd "$3" --stdin")}' nameadd.txt useradd:用户“yuanrundong1”已存在 passwd:未知的用户名 11232dbs。 useradd:用户“hepang”已存在 passwd:未知的用户名 234ndf。 useradd:用户“shiyuqian”已存在
第二种:写脚本进行创建。
[root@localhost shell]# cat nameadd1.txt #!/bin/bash username=($(awk '{print $2}' nameadd.txt)) userpwd=($(awk '{print $3}' nameadd.txt)) for i in $(seq $(cat nameadd.txt|wc -l)) do useradd ${username[i-1]} echo ${userpwd[i-1]}|passwd ${username[i-1]} --stdin done [root@localhost shell]# bash nameadd1.txt useradd:用户“yuanrundong1”已存在 更改用户 yuanrundong1 的密码 。 passwd:所有的身份验证令牌已经成功更新。 useradd:用户“hepang”已存在 更改用户 hepang 的密码 。 passwd:所有的身份验证令牌已经成功更新。 useradd:用户“shiyuqian”已存在 更改用户 shiyuqian 的密码 。 passwd:所有的身份验证令牌已经成功更新。
第三种:使用for循环进行创建。
[root@nginx-kafka01 shell]# cat name.txt yuanrundong1 123456 hepang 123456 shiyuqian 123456 tanxue1 123456 [root@nginx-kafka01 shell]# cat nameadd2.txt #!/bin/bash while read user pwd do useradd $user echo $pwd|passwd $user --stdin done < name.txt [root@nginx-kafka01 shell]# bash nameadd2.txt useradd:用户“yuanrundong1”已存在 更改用户 yuanrundong1 的密码 。 passwd:所有的身份验证令牌已经成功更新。 useradd:用户“hepang”已存在 更改用户 hepang 的密码 。 passwd:所有的身份验证令牌已经成功更新。 useradd:用户“shiyuqian”已存在 更改用户 shiyuqian 的密码 。 passwd:所有的身份验证令牌已经成功更新。 useradd:用户“tanxue1”已存在 更改用户 tanxue1 的密码 。 passwd:所有的身份验证令牌已经成功更新。
6、awk中的数组
awk里的数组下标从1开始。求和、统计。
(1)分类 + 累加求和
[root@localhost shell]# cat ip.txt 172.16.130.26 16274.7 172.16.20.126 8783.61 172.16.130.33 5876.59 173.16.13.145 5389.23 172.16.13.145 5389.23 172.16.13.145 5389.23 172.16.20.126 8783.61 .......... [root@localhost shell]# awk '{ip[$1]+=$2}END{for (i in ip) print i,ip[i]}' ip.txt 173.16.13.145 21556.9 172.16.130.33 5876.59 172.16.13.145 16167.7 172.16.20.126 17567.2 172.16.130.26 16274.7 172.16.145.173 4974.36
将求和的结果进行排序。
[root@localhost shell]# awk '{ip[$1]+=$2}END{for (i in ip) print i,ip[i]}' ip.txt |sort -k2 -nr 173.16.13.145 21556.9 172.16.20.126 17567.2 172.16.130.26 16274.7 172.16.13.145 16167.7 172.16.130.33 5876.59 172.16.145.173 4974.36
(2)统计:门票统计
[root@localhost shell]# cat bill.txt feng 100 feng 200 feng 350 li 200 ma 100000 li 239 li 890 zhang 100 zhang 350 ma 100000 [root@localhost shell]# awk '{bill[$1]+=$2}END{for (i in bill) print i,bill[i]}' bill.txt|sort -k2 -nr ma 200000 li 1329 feng 650 zhang 450 =====
①统计各个省份的票数,输出省份和总票数,按照降序排列
将省份作为key,将票数作为value.
a[$1]:数组
[root@sc-mysql awk]# cat a.txt 山东 aa 2 河南 bb 3 江西 cc 3 湖南 aa 40 山东 bb 10 江西 dd 6 河南 cc 3 湖南 cc 3 [root@localhost shell]# awk '{a[$1]+=$3}END{for (i in a) print i,a[i]}' a.txt|sort -k2 -nr 湖南 43 山东 12 江西 9 河南 6
②已知道一台服务器netstat -anpult输出格式如下:
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 7404/mysqld
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 6086/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 7122/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 7486/master
tcp 0 0 192.168.119.152:22 192.168.119.1:50031 ESTABLISHED 7889/sshd: root@pts
tcp 0 36 192.168.119.152:22 192.168.119.1:56723 ESTABLISHED 9067/sshd: root@pts
tcp 0 0 192.168.119.152:22 192.168.119.1:57028 ESTABLISHED 9181/sshd: root@pts
tcp 0 0 192.168.119.152:22 192.168.119.1:50986 ESTABLISHED 8144/sshd: root@pts
tcp6 0 0 :::111 :::* LISTEN 6086/rpcbind
统计每个state的数量。
[root@localhost shell]# awk 'NR>1{iptest[$6]+=1}END{for (i in iptest) print i,iptest[i]}' iptest.txt|sort -k2 TIME_WAIT 6 ESTABLISHED 6 LISTEN 4
统计输出连接到本机连接数量最多的3个IP,并按连接数从多到少排序(降序)
NR>1:表示从第二行开始。 [root@localhost shell]# awk 'NR>1{if ($6~/ESTABLISHED/)iptest[$5]+=1}END{for (i in iptest) print i,iptest[i]}' iptest.txt|sort -k2 -nr 172.16.17.83:5921 2 172.16.10.25:5921 2 127.0.0.1:35422 2