文本三剑客之awk命令--截取

目录

一.正则表达式

1.1正则表达式简介

1.2 通配符和元字符

1.3 正则:

1.4 其他

 二.awk命令

2.1 awk命令简介

2.2 举例

2.3 分隔符

2.4NF和NR

2.5awk的格式

2.6练习

2.7 awk传参问题

2.8 流控

2.9 数组


一.正则表达式

awk支持正则表达式,并且在匹配的过程中多次使用到正则,所以学习awk之前,我们先了解shell中正则的一些简单使用(其实python中使用正则跟Linux中使用正则的规则都差不多,想详细了解正则表达式,可以查看我之前一篇专门写正则的博客)https://blog.csdn.net/weixin_43880061/article/details/125265593?spm=1001.2014.3001.5502

1.1正则表达式简介

regular expression --》re 正则表达式,简称正则

正则定义(用在哪里):使用一些特殊符号+字母和数字按照某个正确的规则组成一个公式用来表示某个意思,这就叫正则表达式

有什么用:用来查找,根据正则表达式表达出来的意思,去海量的文本里查找符合这个意思的内容

在哪里用:很多的命令都有查找的功能,有查找功能的命令都能使用正则,vim,sed,awk,grep

简单的正则例子:^wangshuai{3}[0-9]+   意思是以wagnshuai开头,i出现3次,数字出现1次以上

1.2 通配符和元字符

通配符:在shell里的叫法

        * 代表任意个字符

        ? 代表一个任意字符串(就是只占一位)

元字符(meta character):在正则表达式里的叫法,用来描述其他字符的字符

        * 前面的字符出现0次或多次

        ? 前面的字符出现0次或1次

        + 前面的字符出现1次或多次

        ^ 表示以什么开头

        $ 表示以什么结尾

        . 占位符 表示一个除\n之外的任意字符

        {n,m} 匹配前一项n到m次

        | 或

1.3 正则:

        1.基本正则:元字符比较少,^,$,*,? grep

        2.扩展正则:+,{},| egrep == grep -E

1.4 其他

grep,匹配模式在行里查找,然后输出,输出匹配模式的行

模式是什么?模式是grep里包含了正则表达式的一个表达式,按照某个模型根据正则表达式去构成一个公式

写正则表达式,就是找共性的特点,找规律

xargs命令:使一列转为一行,还可以将前面命令的输出作为参数传给后面的命令

​
[root@xieshan 0707]# cat mail.txt

  [email protected] fdffaf1212

  [email protected] 8989

  [email protected] fjdkfj

[root@xieshan 0707]# egrep -o "[0-Z_]+@[0-Z]+.[a-Z]+" mail.txt

[email protected]

[email protected]

[email protected]

[root@xieshan 0707]# egrep -o "[0-Z_]+@[0-Z]+.[a-Z]+" mail.txt |xargs

[email protected] [email protected] [email protected]

 二.awk命令

2.1 awk命令简介

awk是一种编程及数据操纵语言,名称来源于创始人的名字缩写

 Gawk  is  the  GNU Project's implementation of the AWK programming language.

GNU是什么?

        GNU is not unix

        GNU 是一个项目,它的宗旨是构建一个不是unix的操作系统

有什么作用?过滤、截取、统计

用在哪里:文本处理(截取和统计)

awk命令工作原理:

与sed一样, 均是一行一行的读取、处理

sed作用于一整行的处理,而awk将一行分成数个字段来处理

awk是依次对每一行进行处理,然后输出

2.2 举例

统计每个用户一共充值了多少钱?--》求和,分类统计
[root@master 77]# cat bill.txt
feng    100
feng    200
feng    350
li    200
ma   100000
li    239
li    890
zhang  100
zhang   350
ma   1000
[root@master 77]# awk '{name[$1]+=$2}END{for (i in name) print i,name[i]}' bill.txt
li 1329
feng 650
zhang 450
ma 101000
[root@master 77]#

name[$1]+=$2 拿$1字段做key,让$2做value,如果数组里有key,就累加,如果没有,初始值是0+value

END{for (i in name) print i,name[i]} END是文件里所有的行都处理完了,最后去执行END部分里的命令

for 循环取遍历name数组里的元素(item),i取name数组里的key,输出key和对应的value

字段 field -->一段长文字被分隔符隔开,形成很多段比较短的文字

列 --》column 字段

一列就是一个字段

行 row line 记录 record

一行就是一条记录

2.3 分隔符

awk截取文本时,会按照指定的分隔符去分隔,默认的分隔符是空格,使用- F可以指定分隔符

1.输入分隔符

        默认是空白(包括空格和tab键)

        -F ":" FS 输入分隔符变量  The input field separator, a space by default.  See Fields,above.

2.输出分隔符

        默认是空格

        OFS="#" out field separater 输出分隔符变量  The output field separator, a space by default.

举例说明:

[root@xieshan 0707]# awk -F ':' '{print $1$3$7}' /etc/passwd|head -5	#没有, 就会紧挨着输出
root0/bin/bash
bin1/sbin/nologin
daemon2/sbin/nologin
adm3/sbin/nologin
lp4/sbin/nologin

[root@xieshan 0707]# awk -F ':' 'OFS="#"{print $1,$3,$7}' /etc/passwd |head -5 #使用 , 就是调用输出分隔符,默认是空格
root#0#/bin/bash
bin#1#/sbin/nologin
daemon#2#/sbin/nologin
adm#3#/sbin/nologin
lp#4#/sbin/nologin
[root@xieshan 0707]# awk -F ':' 'OFS="#"{print $1$3$7}' /etc/passwd |head -5    #如果指定了输出分隔符,但是print后面的变量没有用逗号隔开,那么OFS也不会生效,还是会紧挨着输出
root0/bin/bash
bin1/sbin/nologin
daemon2/sbin/nologin
adm3/sbin/nologin
lp4/sbin/nologin

2.4NF和NR

awk的四个内置变量分别是:FS、OFS、NF、NR

NF          The number of fields in the current input record. 表示最后一个字段,$(NF -1) 倒数第2个字段

NR          The total number of input records seen so far. 表示行号

FS        # 保存或设置字段分隔符,如FS=”:”

OFS     # 输出字段分隔符,默认也是空格,可以改为制表符等

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

$0        # 当前读入的整行文本内容

~            匹配,与==相比不是精确比较,模糊匹配

!~           不匹配,不精确比较

==         等于,必须全部相等,精确比较

!=           不等于,精确比较

&&      逻辑与

||             逻辑或

+            匹配时表示1个或1个以上

/[0-9][0-9]+/   两个或两个以上数字

/[0-9][0-9]*/    一个或一个以上数字

[root@xieshan 0707]# awk -F ':' 'OFS="#"{print $1,$3,$7,$NF}' /etc/passwd|head -5
root#0#/bin/bash#/bin/bash
bin#1#/sbin/nologin#/sbin/nologin
daemon#2#/sbin/nologin#/sbin/nologin
adm#3#/sbin/nologin#/sbin/nologin
lp#4#/sbin/nologin#/sbin/nologin

[root@xieshan 0707]# awk -F ':' 'OFS="#"{print NR,$1,$3,$7}' /etc/passwd|head -5
1#root#0#/bin/bash
2#bin#1#/sbin/nologin
3#daemon#2#/sbin/nologin
4#adm#3#/sbin/nologin
5#lp#4#/sbin/nologin

2.5awk的格式

文本三剑客之awk命令--截取_第1张图片

 文本三剑客之awk命令--截取_第2张图片

 文本三剑客之awk命令--截取_第3张图片

# 格式1
前置命令 | awk [选项] '条件{编辑指令}'

# 格式2
awk [-F|-f|-v] 'BEGIN{} //{command1; command2} END{}' 文件

[-F|-f|-v]    大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
' '            引用代码块
BEGIN       初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
//            匹配代码块,可以是字符串或正则表达式
{}          命令代码块,包含一条或多条命令
;           多条命令使用分号分隔
END         结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息

# 编辑指令如果包含多条语句时,可以用分号分隔,处理文本时,若未指定分隔符,则默认将空格、制表符等作为分隔符。print是最常见的指令。

[root@xieshan 0707]# awk -F: 'BEGIN{print "######start#####"} $3>500&&$3<1000{print $1,$3}END{print "#####end#####"}' /etc/passwd
######start#####
polkitd 999
chrony 998
zabbix 997
nginx 996
#####end#####
[root@xieshan 0707]# awk -F: 'BEGIN{num=0;print "###start###"} $1~/^feng{2,}/ && $3>2000|| $NF ~ /bash/ {print NR,NF,$1,$3,length($1),$(NF-1),$NF;num++} END{print "行数:"num}' /etc/passwd
###start###
1 7 root 0 4 /root /bin/bash
20 7 sc 1000 2 /home/sc /bin/bash
21 7 sc1 1001 3 /home/sc1 /bin/bash
22 7 ll 1002 2 /home/ll /bin/bash
......省略很多个输出
69 7 sanle 2009 5 /home/sanle /bin/bash
70 7 luodayou 2010 8 /home/luodayou /bin/bash
行数:40
[root@xieshan 0707]# 
[root@xieshan 0707]# who|awk '{print "username:"$1" time:"$3}'
username:root time:2022-07-06
username:root time:2022-07-07
username:root time:2022-07-07
username:root time:2022-07-07
[root@xieshan 0707]# awk '{print "username:"$1," uid:"$3}' /etc/passwd|head -5
username:root:x:0:0:root:/root:/bin/bash  uid:
username:bin:x:1:1:bin:/bin:/sbin/nologin  uid:
username:daemon:x:2:2:daemon:/sbin:/sbin/nologin  uid:
username:adm:x:3:4:adm:/var/adm:/sbin/nologin  uid:
username:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin  uid:
[root@xieshan 0707]# awk -F: '/bash/{print "username:"$1," uid:"$3}' /etc/passwd|head -5
username:root  uid:0
username:sc  uid:1000
username:sc1  uid:1001
username:ll  uid:1002
username:kim  uid:1003
[root@xieshan 0707]# awk -F: '/feng/{print "username:"$1," uid:"$3}' /etc/passwd|head -5
username:califeng  uid:1025
[root@xieshan 0707]# awk -F: '$1~/feng/{print "username:"$1," uid:"$3}' /etc/passwd|head -5
username:califeng  uid:1025
[root@xieshan 0707]# 
[root@xieshan 0707]# awk -F'[:/]' '{print $1,$10}' /etc/passwd|head
root bash
bin nologin
daemon nologin
adm sbin
lp 
sync sync
shutdown shutdown
halt halt
mail 
operator nologin
[root@xieshan 0707]# vim grade.txt
[root@xieshan 0707]# cat grade.txt 
id     name     chinese     math     english
1      cali      80         80        80
2      rose      90         98        29
3      tom       89         98        89
4      jenny     100        60        90
[root@xieshan 0707]# awk '{print $2,$3}' grade.txt 
name chinese
cali 80
rose 90
tom 89
Jenny 100
[root@xieshan 0707]# vim grade.txt
[root@xieshan 0707]# cat grade.txt 
id     name     chinese     math     english//linux
1      cali      80         80        80//90
2      rose      90         98        29//99
3      tom       89         98        89//78
4      jenny     100        60        90//77
[root@xieshan 0707]# awk -F'[ /]+' '{print $2,$3,$6}' grade.txt   #+表示连续的多个分隔符当成一个分隔符使用,这里的分隔符有空格和/
name chinese linux
cali 80 90
rose 90 99
tom 89 78
jenny 100 77
[root@xieshan 0707]# awk '{gsub("/"," ",$5);print $2,$3,$5}' grade.txt 	#gsub是把$5的/替换成空格,并且当成一个整体$5
name chinese english  linux
cali 80 80  90
rose 90 29  99
tom 89 89  78
jenny 100 90  77
tr命令:字符转换和删除的命令
-s		压缩连续的相同的字符串为同一个字符
-d		删除字符串
[root@xieshan 0707]# cat grade.txt |tr '//' "\t"	#将//转换成一个tab键
id     name     chinese     math    english		linux
1      cali      80         80        80		90
2      rose      90         98        29		99
3      tom       89         98        89		78
4      jenny     100        60        90		77
[root@xieshan 0707]# cat grade.txt |tr -s "/"
id     name     chinese     math    english/linux
1      cali      80         80        80/90
2      rose      90         98        29/99
3      tom       89         98        89/78
4      jenny     100        60        90/77
[root@xieshan 0707]# cat grade.txt |tr -s "/ "		#压缩连续相同的/或者空格
id name chinese math english/linux
1 cali 80 80 80/90
2 rose 90 98 29/99
3 tom 89 98 89/78
4 jenny 100 60 90/77
[root@xieshan 0707]# cat grade.txt |tr -s "/" " "	#将/用空格替换
id name chinese math english linux
1 cali 80 80 80 90
2 rose 90 98 29 99
3 tom 89 98 89 78
4 jenny 100 60 90 77
[root@xieshan 0707]# echo aaaabbbbbbababccab123 |tr ab 89		#将ab替换成89
88889999998989cc89123
[root@xieshan 0707]# awk -F: '$3 ~ /[0-9]{5}/{print $1,$3}' /etc/passwd
nfsnobody 65534
[root@xieshan 0707]# awk -F: '$1 ~ /\/{print $1,$3}' /etc/passwd
luoziyao 2011
输出/etc/passwd里面,uid大于1000,并且shell用的是bash,统计有多少个
[root@xieshan 0707]# awk -F: 'BEGIN{num=0}$7~/bash/&&$3>1000{print $3,$7;num++}END{print "行数:"num}' /etc/passwd
1001 /bin/bash
1002 /bin/bash
......省略很多个输出
2010 /bin/bash
2011 /bin/bash
行数:39
[root@xieshan 0707]# 
awk实现输出/etc/passwd的第一行和最后1行
===============未使用awk
[root@xieshan 0707]# head -1 /etc/passwd;tail -1 /etc/passwd
root:x:0:0:root:/root:/bin/bash
luoziyao:x:2011:2011::/home/luoziyao:/bin/bash
===============使用awk
[root@xieshan 0707]# awk 'NR==1{print NR,$0}END{print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
71 luoziyao:x:2011:2011::/home/luoziyao:/bin/bash

2.6练习

文本三剑客之awk命令--截取_第4张图片

 答案:

1.[root@xieshan 0707]# df -h|awk '{print $1}'
2.[root@xieshan 0707]# awk -F: 'NR==5||NR==10{print NR,$1}' /etc/passwd
3.[root@xieshan 0707]# awk -F: '{print $(NF-1)}' /etc/passwd
4.[root@xieshan 0707]# awk -F: 'NR>=5&&NR<=10 {print $1}' /etc/passwd 
5.[root@xieshan 0707]# awk -F: '$7 !~/bash/ {print $1}' /etc/passwd 
6.[root@xieshan 0707]# awk -F: 'NR~/.5/ {print NR,$0}' /etc/passwd 
   [root@xieshan 0707]# awk -F: 'NR~/5$/ {print NR,$0}' /etc/passwd
7.[root@xieshan 0707]# ip a|awk '$1 ~/^inet$/ && $3 ~/brd/ {print $2,$3}' 
8.[root@xieshan 0707]# ifconfig ens33|awk -F' ' '$2 ~/packets/ {print $1,$5}'
   [root@xieshan 0707]# ifconfig|egrep -A8 "^ens33"|awk '/RX p/ || /TX p/{print $1,$5}'
9.[root@xieshan 0707]# awk -F: 'BEGIN{num=0}$1 ~/^r/ {print $1;num++}END{print "一共有"num"个用户以r开头"}' /etc/passwd
10.[root@xieshan 0707]# watch -n 2 -d "ifconfig|awk 'NR==5{print $5}'"
     [root@xieshan 0707]# watch -n 2 -d "ifconfig|egrep -A8 "^ens33"|awk '/RX p/ || /TX p/{print \$5}'"
watch命令:
-n  interval seconds   指定间隔时间			-d    高亮显示
11.[root@xieshan 0707]# awk -F: 'BEGIN{print"查找结果:";num=0}$1 ~/^r/ {print $1;num++}END{print "行数:"num}' /etc/passwd

2.7 awk传参问题

在awk内部调用变量,不需要添加$符号,只有位置变量必须要添加$

在awk中使用,引用的shell变量不需要转义,但是要加$符号,但是位置变量需要转义,注意这里使用双引号

[root@xieshan 0707]# echo $$		#查看当前进程的pid
8184
[root@xieshan 0707]# awk '{print PROCINFO["pid"],PROCINFO["ppid"]}' /etc/passwd	#PROCINFO这个数组是awk内置数组,用来存储进程相关信息

[root@xieshan 0707]# sg=renhaodong		#shell中定义的变量
[root@xieshan 0707]# useradd renhaodong
[root@xieshan 0707]# awk '/sg/{print $1}' /etc/passwd
[root@xieshan 0707]# awk "/sg/{print $1}" /etc/passwd
[root@xieshan 0707]# awk "/$sg/{print \$1}" /etc/passwd	#在awk中使用,引用的shell变量不需要转义,但是要加$符号,但是位置变量需要转义,注意这里使用双引号
renhaodong:x:2012:2012::/home/renhaodong:/bin/bash

2.8 流控

文本三剑客之awk命令--截取_第5张图片

流控:following control

if:if(condition )

for

函数:

length 统计长度

split 将一段字符串根据分隔符号,对文本进行分隔,存放到数组里,使用for循环遍历读取数组里的内容

gsub 替换

substr 截取部分字符串

toupper [root@xieshan 0707]# awk -F: '{print toupper($1)}' /etc/passwd

tolower [root@xieshan 0707]# awk -F: '{print tolower($1)}' /etc/passwd

2.9 数组

文本三剑客之awk命令--截取_第6张图片

数组:awk里的数组下标从1开始

求和

统计

air -condition ---AC

awk里的for循环格式:

for (i=0;i<10;i++) {print $i;}

for (i in array){print array[i]} -->直接从数组的下标里读一个值,以此类推取完所有的值,遍历

python里字典:key:value

[root@xieshan 0707]# awk -F: '{if ($1 ~/renhaodong/) print "haoge"}' /etc/passwd	#单分支
haoge
[root@xieshan 0707]# awk -F: '{if ($1 ~/renhaodong/) print "haoge";else print "dage"}' /etc/passwd	#双分支
[root@xieshan 0707]# awk -F: '{if ($1 ~/renhaodong/) print "haoge";else if ($3>5000) print "dageda";else print "dage"}' /etc/passwd		#多分支
[root@xieshan 0707]# awk -F: '{if ($3 == 0) print "超级用户";else if ($3>=1&&$3<=999) print "系统用户";else print "普通用户"}' /etc/passwd
[root@xieshan 0707]# awk -F: 'BEGIN{num1=0;num2=0;num3=0}{if ($3 == 0) num1++;else if ($3>=1&&$3<=999) num2++;else num3++}END{print "一共有超级用户:"num1,"一 有系统用户:"num2,"一共有普通用户:"num3}' /etc/passwd
一共有超级用户:1 一共有系统用户:26 一共有普通用户:45
[root@xieshan 0707]# awk -F: '{if ($3 == 0) num1++;else if ($3>=1&&$3<=999) num2++;else num3++}END{print "一共有超级用户:"num1,"一共有系统用户:"num2,"一共有 通用户:"num3}' /etc/passwd	#不提前定义也可以
一共有超级用户:1 一共有系统用户:26 一共有普通用户:45
[root@xieshan 0707]# 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	#多条命令使用花括号,不需要再接分号

[root@xieshan 0707]# awk -F: 'length($1) > 6{print $1}' /etc/passwd		
[root@xieshan 0707]# awk -F: '{if (length($1) > 6) print $1}' /etc/passwd
[root@xieshan 0707]# awk -F: '{if (length($1) > 6) print substr($1,1,5)}' /etc/passwd |head -5
split切割:python中和awk一致
>>> mn = "aojiao wangzuxian luoziyao shiyuqian"
>>> mns = mn.split()
>>> mns
['aojiao', 'wangzuxian', 'luoziyao', 'shiyuqian']
>>> sg = "wang/feng/xie/li/zeng/yang"
>>> sg2 = sg.split("/")
>>> sg2
['wang', 'feng', 'xie', 'li', 'zeng', 'yang']
awk里面的数组下标从1开始
[root@xieshan 0707]# awk -F: '{split($6,home_dir,"/")}END{for (i in home_dir)print i,home_dir[i]}' /etc/passwd
[root@xieshan 0707]# awk -F: '{split($6,home_dir,"/");for (i in home_dir)print i,home_dir[i]}' /etc/passwd
[root@xieshan 0707]# awk -F: '{split($6,home_dir,"/");for (i=2;i<4;i++)print i,home_dir[i]}' /etc/passwd

根据一个文件里的内容,批量新建用户和设置密码:

[root@xieshan 0707]# awk '{system("useradd " $1)}' name.txt   	#调用shell命令

方法一:
[root@xieshan 0707]# awk '{system("useradd "$1);system("echo "$2"| passwd "$1" --stdin")}' name.txt
方法二:
[root@xieshan 0707]# cat adduser.sh 
#!/bin/bash
while read user pwd
do
	useradd $user
	echo $pwd|passwd $user --stdin
done < name.txt
方法三:
[root@xieshan 0707]# cat useradd_multi.sh 
#!/bin/bash
username=($(awk '{print $1}' name.txt))	#成为一个数组
userpwd=($(awk '{print $2}' name.txt))	#也是数组
for i in $(seq $(cat name.txt|wc -l))
do	
		useradd ${username[i-1]}
		echo ${userpwd[i-1]}|passwd ${username[i-1]} --stdin
done
对/etc/passwd的第三列求和:
[root@xieshan 0707]# awk -F: '{sum+=$3}END{print sum}' /etc/passwd
136000
对1-100进行求和:
[root@xieshan 0707]# seq 100|awk '{sum+=$1}END{print sum}'
5050

分类+累加求和

统计相同的ip的流量:

[root@xieshan 0707]# 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
172.16.145.173 4974.36
172.16.13.145 5389.23
173.16.13.145 5389.23
173.16.13.145 5389.23
173.16.13.145 5389.23
[root@xieshan 0707]# 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

统计每个人的充值数额,按照升序排序:

[root@xieshan 0707]# cat bill.txt 
feng    100
feng    200
feng    350
li    200
ma   100000
li    239
li    890
zhang  100
zhang   350
ma   1000
[root@xieshan 0707]# awk '{bill[$1]+=$2}END{for (i in bill)print i,bill[i]}' bill.txt |sort -k2 -n
zhang 450
feng 650
li 1329
ma 101000

统计各个省份的票数,输出省份和总票数,按照降序排序:

[root@xieshan 0707]# cat a.txt 
山东 aa  2
河南 bb  3
江西 cc 3
湖南 aa 40
山东 bb 10
江西 dd 6
河南 cc 3
湖南 cc 3
[root@xieshan 0707]# awk '{a[$1]+=$3}END{for (i in a)print i,a[i]}' a.txt |sort -k2 -nr
湖南 43
山东 12
江西 9
河南 6

使用netstat -anplut命令得到一个文本:

1、统计每个state的数量

2、统计输出连接到本主机连接数最多的3个IP,并按连接数从多到少排序(降序)

 3、用IP简单的正则匹配上面出现的所有的IP

[root@xieshan 0707]# cat address.txt 
Proto Recv-Q Send-Q Local Address               Foreign Address             State
  tcp        0      0 172.16.18.227:38734         172.16.10.25:5921           ESTABLISHED 
  tcp        0      0 172.16.18.227:33046         172.16.17.83:5921           ESTABLISHED 
  tcp        0      0 127.0.0.1:38978             127.0.0.1:12321             TIME_WAIT   
  tcp        0      0 127.0.0.1:38990             127.0.0.1:12321             TIME_WAIT     
  tcp        0      0 127.0.0.1:3306              127.0.0.1:35422             ESTABLISHED 
  tcp        0      0 127.0.0.1:38912             127.0.0.1:12321             TIME_WAIT  
  tcp        0      0 172.16.18.227:38734         172.16.10.25:5921           ESTABLISHED 
  tcp        0      0 172.16.18.227:33046         172.16.17.83:5921           ESTABLISHED 
  tcp        0      0 127.0.0.1:38978             127.0.0.1:12321             TIME_WAIT   
  tcp        0      0 127.0.0.1:38990             127.0.0.1:12321             TIME_WAIT     
  tcp        0      0 127.0.0.1:3306              127.0.0.1:35422             ESTABLISHED 
  tcp        0      0 127.0.0.1:38912             127.0.0.1:12321             TIME_WAIT 
  tcp        0      0 127.0.0.1:10248             0.0.0.0:*               LISTEN      978/kubelet         
  tcp        0      0 127.0.0.1:10249              0.0.0.0:*               LISTEN      3146/kube-proxy     
  tcp        0      0 192.168.2.130:2379          0.0.0.0:*               LISTEN      2650/etcd           
  tcp        0      0 127.0.0.1:2379               0.0.0.0:*               LISTEN      2650/etcd  
1、统计每个state的数量
[root@xieshan 0707]# awk 'NR>1{a[$6]+=1}END{for (i in a)print i,a[i]}' address.txt |sort -k2 -nr
TIME_WAIT 6
ESTABLISHED 6
LISTEN 4
2、统计输出连接到本主机连接数最多的3个IP,并按连接数从多到少排序(降序)
[root@xieshan 0707]# awk '$6=="ESTABLISHED"{a[$5]+=1}END{for (i in a)print i,a[i]}' address.txt |sort -k2 -nr
172.16.17.83:5921 2
172.16.10.25:5921 2
127.0.0.1:35422 2
 3、用IP简单的正则匹配上面出现的所有的IP
[root@xieshan 0707]# awk '$4,$5 ~/^((25[0-5]|2[0-4]\d|1?\d\d?)\.){3}(25[0-5]|2[0-4]\d|1?\d\d?)$/{print $4,$5}' address.txt 
Local Address
172.16.18.227:38734 172.16.10.25:5921
172.16.18.227:33046 172.16.17.83:5921
127.0.0.1:38978 127.0.0.1:12321
127.0.0.1:38990 127.0.0.1:12321
127.0.0.1:3306 127.0.0.1:35422
127.0.0.1:38912 127.0.0.1:12321
172.16.18.227:38734 172.16.10.25:5921
172.16.18.227:33046 172.16.17.83:5921
127.0.0.1:38978 127.0.0.1:12321
127.0.0.1:38990 127.0.0.1:12321
127.0.0.1:3306 127.0.0.1:35422
127.0.0.1:38912 127.0.0.1:12321
127.0.0.1:10248 0.0.0.0:*
127.0.0.1:10249 0.0.0.0:*
192.168.2.130:2379 0.0.0.0:*
127.0.0.1:2379 0.0.0.0:*

有一个nginx的日志文件:

1.计算每分钟的带宽

2.统计每个URI(即不带问号?后面的内容)的每分钟的频率

[root@xieshan 0707]# cat nginx.log 
##以下是nginx日志的字段含义
##$time_iso8601|$host|$http_cf_connecting_ip|$request|$status|$body_bytes_sent|$http_referer|$http_user_agent
2019-04-25T09:51:58+08:00|a.google.com|47.52.197.27|GET /v2/depth?symbol=aaa HTTP/1.1|200|24|-|apple
2019-04-25T09:52:58+08:00|b.google.com|47.75.159.123|GET /v2/depth?symbol=bbb HTTP/1.1|200|407|-|python-requests/2.20.0
2019-04-25T09:54:58+08:00|d.shuzibi.co|-||HEAD /justfor.txt HTTP/1.0|200|0|-|-
2019-04-25T09:55:58+08:00|e.google.com|13.251.98.2|GET /v2/order_detail?apiKey=ddd HTTP/1.1|200|231|-|python-requests/2.18.4
2019-04-25T09:56:58+08:00|f.google.com|210.3.168.106|GET /v2/trade_detail?apiKey=eee HTTP/1.1|200|24|-|-
2019-04-25T09:57:58+08:00|g.google.com|47.75.115.217|GET /v2/depth?symbol=fff HTTP/1.1|200|397|-|python-requests/2.18.4
2019-04-25T09:58:58+08:00|h.google.com|47.75.58.56|GET /v2/depth?symbol=ggg HTTP/1.1|200|404|-|safari
2019-04-25T09:54:58+08:00|d.shuzibi.co|-||HEAD /justfor.txt HTTP/1.0|200|0|-|-
2019-04-25T09:55:58+08:00|e.google.com|13.251.98.2|GET /v2/order_detail?apiKey=ddd HTTP/1.1|200|231|-|python-requests/2.18.4
2019-04-25T09:56:58+08:00|f.google.com|210.3.168.106|GET /v2/trade_detail?apiKey=eee HTTP/1.1|200|24|-|-
2019-04-25T09:59:58+08:00|i.google.com|188.40.137.175|GET /v2/trade_detail?symbol=hhh HTTP/1.1|200|6644|-|-
2019-04-25T09:59:58+08:00|i.google.com|188.40.137.175|GET /v2/trade_detail?symbol=hhh HTTP/1.1|200|6644|-|-
2019-04-25T09:59:58+08:00|i.google.com|188.40.137.175|GET /v2/trade_detail?symbol=hhh HTTP/1.1|200|6644|-|-
2019-04-25T09:59:58+08:00|i.google.com|188.40.137.175|GET /v2/trade_detail?symbol=hhh HTTP/1.1|200|6644|-|-
2019-04-25T10:01:58+08:00|j.google.com|2600:3c01:0:0:f03c:91ff:fe60:49b8|GET /v2/myposition?apiKey=jjj HTTP/1.1|200|110|-|scan
2019-04-25T09:58:58+08:00|h.google.com|47.75.58.56|GET /v2/depth?symbol=ggg HTTP/1.1|200|404|-|safari
2019-04-25T09:59:58+08:00|i.google.com|188.40.137.175|GET /v2/trade_detail?symbol=hhh HTTP/1.1|200|6644|-|-
2019-04-25T10:01:58+08:00|j.google.com|2600:3c01:0:0:f03c:91ff:fe60:49b8|GET /v2/myposition?apiKey=jjj HTTP/1.1|200|110|-|scan
计算每分钟的带宽
用时间做key,body_bytes_sent做value,进行累计
[root@xieshan 0707]#  awk -F"|" '{traffic[substr($1,1,16)]+=$6}END{for (i in traffic) print i,traffic[i]}' nginx.log|sort -k2 -nr|head -5
2019-04-25T09:59 33220
2019-04-25T09:58 808
2019-04-25T09:55 462
2019-04-25T09:52 407
2019-04-25T09:54 400
统计每个URI(即不带问号?后面的内容)的每分钟的频率
以时间+uri作为key值,出现次数作为value
[root@xieshan 0707]# awk -F"[ |?]+" '{uri[substr($1,1,16)$5]+=1}END{for (i in uri)print i,uri[i]}' nginx.log |sort -k2 -nr|head -3
2019-04-25T09:59/v2/trade_detail 5
2019-04-25T10:01/v2/myposition 2
2019-04-25T09:58/v2/depth 2

awk可以对日志文件进行分析

数据采集/收集--》清洗数据--》数据集--》数据仓库---》数据分析

##########################

求取grade.txt中,每科成绩中分数最高的人和它的姓名

[root@xieshan lianxi]# vim grade.txt 
[root@xieshan lianxi]# cat grade.txt 
学生A 语文 100 
学生B 数学 90 
学生A 英语 99 
学生C 语文 80
学生B 英语 56
[root@xieshan lianxi]# awk '{if (a[$2]<$3) {a[$2]=$3;b[$2]=$1}}END{for (i in a)print "科目:"i,"分数:"a[i],"姓名:"b[i]}' grade.txt 
科目:语文 分数:100 姓名:学生A
科目:数学 分数:90 姓名:学生B
科目:英语 分数:99 姓名:学生A

在上面这个例子中,a[$2]代表的其实是分数,b[$2]代表的是姓名,这都是自己定义的;可以理解为$2--->a[$2]以及$2--->b[$2]

你可能感兴趣的:(Linux,大数据,运维,linux)