文本三剑客——awk 截取+过滤+统计(2)

简介: 文本三剑客——awk 截取+过滤+统计

文本三剑客——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


相关文章
|
6月前
|
Unix Shell Linux
如何使用 Awk 打印文件中的字段和列
如何使用 Awk 打印文件中的字段和列
137 0
|
4月前
|
存储 Shell Linux
文本三剑客——awk 截取+过滤+统计(1)
文本三剑客——awk 截取+过滤+统计
|
5月前
|
编译器 C语言
字符串\统计字符
字符串\统计字符
36 3
|
4月前
|
Shell 网络安全 开发工具
文本三剑客——grep过滤
文本三剑客——grep过滤
|
6月前
|
安全
如何快速断行、分割行、切割行、换行、限制每行字数、平均分割每行字数、序号自动换行、关键字断行等等内容格式整理
该工具用于文本格式处理,能调整每行字数、进行内容断行、提取特定格式内容等。在示例中,展示了如何将一段“交通安全教育”文字按30字每行分隔,并整理出带序号的格式。工具支持序号断行和多级序号设置,适用于笔记整理、文档格式化和内容布局优化,能提升工作效率。下载工具可从百度网盘(提取码:qwu2)或蓝奏云(提取码:2r1z)获取。
|
6月前
|
弹性计算 运维 Shell
使用cut提取子串
【4月更文挑战第29天】
39 2
|
Shell
Shell 过滤数据(cut 截取过滤列)
Shell 过滤数据(cut 截取过滤列)
92 0
R7-2 统计字符[2]
R7-2 统计字符[2]
98 0
|
索引 Perl
AWK进行简单分析文本
AWK进行简单分析文本
82 0