1、基本应用
# -F 后单引号''中的值为自定义分隔符 '{print }'为要打印出来的内容 $后的值为要打印的内容在分割后内容的位置(占分割后的第几个字段,数字从1开始)
# grep命令为筛选,只筛选出包含固定值的行
# awk '!a[$0]++'命令为去重,即第二次出现某字符时不进行取值
# sort命令为排序
# 日志文件access_log.log的内容,先按双引号分割,取第2个字段值,然后取出的内容,按空格分割,取第2个字段值,然后取出的内容,按?分割,取第1个字段值。然后将取出的内容中包含v1字符的行数取出,去重排序后,追加到request.log文件中
$ cat access_log.log | awk -F '"' '{print $2}' | awk -F ' ' '{print $2}' | awk -F '?' '{print $1}'| grep 'v1' | awk '!a[$0]++' | sort >> request.log
# 例如以上命令取出的内容为:
# /api/v1/
# /nacos/v1/core/cluster/nodes
# /v1/ai/ocr
# /v1/clouddoc/chat_addshare
# /v1/clouddoc/chat_download
特殊字符作为分隔符
# 以单引号为分隔符截取(-F后的匹配全部是单引号,没有双引号)
$ cat router.txt | awk -F ''\''' '{print $1}' > jiequ.txt
# 以单引号或//为分隔符截取(-F后的匹配全部是单引号,没有双引号) 多种分隔符号以|连接 //为一个整体字符
$ cat router.txt | awk -F ''\''|//' '{print $1}' > jiequ.txt
# print打印的多个字段连接符用双引号包裹 以下将两个字段用字符串【 //】连接
$ cat router.txt | awk -F ''\''|//' '{print $1" //"$5}' > jiequ&zhushi.txt
# 例如:
# /v1/note/delnote' => 'actions/api/DelNote.php',//删除笔记
# 执行上述命令后将【/v1/note/delnote】和【删除笔记】用【 //】拼接后输出:
# /v1/note/delnote //删除笔记
# 以[]等特殊字符为分隔符截取 以下命令为以]字符分割,需要转义
# 测试来看,以单独字符作为分隔符时,\\]与\]与]实现的分割效果是一致的,如果分隔符为字符串时,必须用\\转义
$ cat router.txt | awk -F '\\]' '{print $1}' > jiequ.txt
# 以完整字符串 ] cost_time[ 分割
$ cat router.txt | awk -F '\\] cost_time\\[' '{print $1}' > jiequ.txt
# 如 xxx] cost_time[123.01] params[ 被分割为两部分【xxx】与【123.01] params[】
# 以字符[或]分割
$ cat router.txt | awk -F '\\[|\\]' '{print $1}' > jiequ.txt
# 如 xxx] cost_time[123.01] params[ 被分割为几部分【xxx】、【 cost_time】、【123.01】、【 params】
数量统计,可用于访问总量计算
# wc -l 查询符合条件的数据行数
$ cat access_log | grep '28/Oct/2021' | wc -l
191626
# 前边的awk命令筛选符合条件的每行的某字段值
# awk '{sum+=$1} END {print "Average = ", sum/NR}' 命令计算所有行的某字段值的平均值
$ cat log/access_log | grep '28/Oct/2021' | awk -F "\"" '{printf $7"\n"}' | awk -F " " '{printf $1"\n"}' | awk '{sum+=$1} END {print "Average = ", sum/NR}'
Average = 0.480158
其他命令结合使用
# 结合判断条件
# 增加条件 cmdtest.txt测试文件中仅一行数据 以下命令是筛选输出符合条件的行 全部数据不符合条件则没有输出
$ cat cmdtest.txt
DEBUG: 21-08-30 00:01:50 [/home/script/sync_put_file_to_neisou.php:31] errno[0] logId[3364879408] module[neisou] spanid[0] force_sampling[0] uri[] refer[] cookie[] redis_key[list:disk:toneisou:13] list[a:2:{s:4:"f_id";i:12345;s:6:"source";s:3:"doc";}] cost_time[0.0171] optime[1630252910.514] file id out list
$ cat cmdtest.txt | awk -F '\\[|\\]' '{print $4}'
0
$ cat cmdtest.txt | awk -F '\\[|\\]' '$4 == 1'
$ cat cmdtest.txt | awk -F '\\[|\\]' '$4 == 0'
DEBUG: 21-08-30 00:01:50 [/home/script/sync_put_file_to_neisou.php:31] errno[0] logId[3364879408] module[neisou] spanid[0] force_sampling[0] uri[] refer[] cookie[] redis_key[list:disk:toneisou:13] list[a:2:{s:4:"f_id";i:12345;s:6:"source";s:3:"doc";}] cost_time[0.0171] optime[1630252910.514] file id out list
$ cat cmdtest.txt | awk -F '\\[|\\]' '$4>0'
$ cat cmdtest.txt | awk -F '\\[|\\]' '$4 >= 0'
DEBUG: 21-08-30 00:01:50 [/home/script/sync_put_file_to_neisou.php:31] errno[0] logId[3364879408] module[neisou] spanid[0] force_sampling[0] uri[] refer[] cookie[] redis_key[list:disk:toneisou:13] list[a:2:{s:4:"f_id";i:12345;s:6:"source";s:3:"doc";}] cost_time[0.0171] optime[1630252910.514] file id out list
# 筛选nginx访问日志 默认以空格分割时,第四个字段值为访问时间,形式如[03/Mar/2021:22:10:04];第九个字段值为httpcode
# awk默认是以行为单位处理文本的,对每行都执行"{ }"中的语句。$0表示一个记录,即当前整行
# 下述命令表示截取掉访问时间字段值中的[]后,判断时间在03/Mar/2021:22:00:00~03/Mar/2021:23:55:00区间内的行,拿到符合条件的行的整行记录,后取出每行第9个字段值httpcode,筛选包含500字符的行,计算行数
$ cat access_log.log | awk '{split($4,array,"[");split(array[2],array2,"]");if(array2[1] >= "03/Mar/2021:22:00:00" && array2[1] <= "03/Mar/2021:23:55:00"){print($0)}}' | awk -F ' ' '{print $9 }' | grep 500 | wc -l
# 可用于统计qps 筛选nginx访问日志的请求时间字段(秒级别 11/Feb/2022:11:29:51),去重统计各时间点的请求日志条数
# uniq -c 去重,并显示该行重复次数
# sort -k1nr 以第1个区间数值方式倒序排序 sort -k2nr -t '|' 以按字符|分割后的第2个字段数值方式倒序排序
# head -50 取前50行 或 head -n 50
$ cat access_log.log | grep '18/Nov/2021' | awk '{print $5}' | awk -F '/' '{print $3}' | awk -F '.' '{print $1}' | uniq -c | sort -k1nr | head -50
# 结合正则匹配
$ netstat -n | head -10
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:58350 127.0.1.1:432 ESTABLISHED
tcp 0 0 10.12.185.161:55618 10.193.185.14:11025 TIME_WAIT
tcp 0 0 10.12.185.161:46748 10.216.48.29:11025 TIME_WAIT
tcp 0 0 127.0.0.1:47988 127.0.0.1:792 TIME_WAIT
tcp 0 48 10.12.185.161:22 172.22.4.19:41050 ESTABLISHED
tcp 0 0 10.12.185.161:50858 100.67.0.24:80 TIME_WAIT
tcp 0 0 127.0.0.1:41384 127.0.0.1:793 TIME_WAIT
tcp 0 0 10.12.185.161:56608 10.161.23.169:8210 TIME_WAIT
# /^tcp/正则匹配规则 匹配以tcp开头的行
# $NF表示分割后的最后一个字段值 awk不标识分隔符时,默认以空格分割
# 结合语法,++运算符累计重复值次数
$ netstat -n | head -10 | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
TIME_WAIT 6
ESTABLISHED 2
# 更改打印字段的分隔字符
$ netstat -n | head -10 | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a"---"S[a]}'
TIME_WAIT---6
ESTABLISHED---2
2、字符替换
$ awk -F "|" '{if ($4==11) {$4="添加空间"} else if ($4==21) {$4="删除空间"} else if ($4==31) {$4="编辑空间"} else if ($4==32) {$4="修改权限"} else if ($4==111) {$4="添加文件夹"} else if ($4==112) {$4="在线创建文件夹"} else if ($4==113) {$4="上传文件"} else if ($4==114) {$4="上传备份文件"} else if ($4==115) {$4="从HI转存至企业云"} else if ($4==116) {$4="复制文件"} else if ($4==121) {$4="删除文件"} else if ($4==131) {$4="在线编辑文件内容"} else if ($4==132) {$4="重命名文件"} else if ($4==133) {$4="移动文件"} else if ($4==134) {$4="恢复文件"} else if ($4==141) {$4="分享文件"} else if ($4==142) {$4="下载文件"} else if ($4==143) {$4="批量下载文件"} else if ($4==144) {$4="预览"} else if ($4==145) {$4="对外分享"} else if ($4==146) {$4="idc获取文件列表"} else if ($4==191) {$4="outlook附件下载"} else if ($4==192) {$4="outlook附件预览"} else if ($4==193) {$4="outlook绑定设备成功"} else if ($4==194) {$4="outlook上传附件"} else if ($4==195) {$4="outlook选取云盘附件"} else if ($4==200) {$4="外部服务下载"} else if ($4==201) {$4="获取用户失败"} else if ($4==231) {$4="下载客户端"}}1' cmdtest.txt > cmdtest_awk.txt
源文件cmdtest.txt内容
执行awk命令后导出的目标文件cmdtest_awk.txt内容