学习自https://www.cnblogs.com/jiqianqian/p/7944013.html
https://www.cnblogs.com/276815076/p/6410179.html
感谢两位博主
一.awk命令简介
1.awk是一种编程语言,用于对文本和数据进行处理
2.具有强大的文本格式化能力
3.awk是逐行进行处理的
二.grep、sed、awk比较
1.grep更适合单纯的查找或匹配文本
2.sed更适合对匹配到的文本进行编辑
3.命令awk更适合文本格式化,对文本进行较复杂的格式处理
三.awk基本语法
awk [options] 'pattern{action}' file
eg:vim test.txt
ABC 123 Jack
DEF 456 Alice
GHI 789 Amy
1.在没有options和pattern的情况下
awk '{print}' test.txt//输出全文
awk '{print $2}' test.txt//输出第二列
awk '{print $2$1$3}' test.txt//调整第二列和第一列,并去掉中间的空格
awk '{print $1,$2+1,$3}' test.txt//输出全文,第二列做+1计算
2.pattern包括两种特殊模式,分别是BEGIN和END
(1)BEGIN模式,是指命令在处理文本之前执行
awk 'BEGIN{print "col1","col2","col3"}{print}' test.txt
col1 col2 col3
ABC 123 Jack
DEF 456 Alice
GHI 789 Amy
(2)END模式,是指命令在处理文本之后执行
awk '{print} END{print "end1","end2","end3"}' test.txt
ABC 123 Jack
DEF 456 Alice
GHI 789 Amy
end1 end2 end3
(3)BEGIN和END同时存在时,其中,BEGIN和END之间的{}相当于一个循环体,对文件中的每一行进行处理
awk 'BEGIN{print "col1","col2","col3"} {print} END{print "end1","end2","end3"}' test.txt
col1 col2 col3
ABC 123 Jack
DEF 456 Alice
GHI 789 Amy
end1 end2 end3
3.常用的参数
(1) -F,用于指定输入分隔符
cp test.txt z.txt
sed -i 's/查找字段/替换字段/g' file
sed -i 's/ /:/g' z.txt//查找空格,用:替换
cat z.txt
ABC:123:Jack
DEF:456:Alice
GHI:789:Amy
awk -F':' '{print $1,$2}' z.txt//以:分割
awk -F' ' '{print $1,$2}' test.txt
(2) -v,用于设置变量的值
echo | awk -v v=100 '{print v}'
echo | awk -v v1=1 -v v2=2 '{print v1,v2}'
四.变量
awk中变量分为内置变量和自定义变量两种
1.内置变量
FS 输入字段分隔符,默认为空白字符
OFS 输出字段分隔符,默认为空白字符
RS 输入记录分隔符(输入换行符),指定输入时的换行符
ORS 输出记录分隔符(输出换行符),指定输出时的换行符
NF 当前行的字段数(当前行被分隔符分割成了几段)
NR 当前行的行号
FNR 不同文件分别计数
FILENAME 当前文件名
ARGV 数组,保存的是命令行所给定的各参数
ARGC ARGV数组的个数
需要注意的是使用变量时,要使用-v选项指定对应的变量
awk -v FS=':' -v OFS='#' '{print $1,$2}' z.txt
ABC#123
DEF#456
GHI#789
awk -v FS=':' -v OFS='#' -v ORS='\n+++\n' '{print $1,$2}' z.txt
ABC#123
+++
DEF#456
+++
GHI#789
+++
awk -v RS='\n' '{print NR,$0}' test.txt//以\n为换行符,输出行号和每行内容
1 ABC 123 Jack
2 DEF 456 Alice
3 GHI 789 Amy
NF:当前行的字段数,其中$NF表示的是最后一个字段的内容,$(NF-1)表示的是倒数第二个字段的内容
awk '{print NF,$0}' test.txt
3 ABC 123 Jack
3 DEF 456 Alice
3 GHI 789 Amy
awk '{print NF,$0,$1}' test.txt
3 ABC 123 Jack ABC
3 DEF 456 Alice DEF
3 GHI 789 Amy GHI
awk '{print NF,$NF,$0,$1}' test.txt
3 Jack ABC 123 Jack ABC
3 Alice DEF 456 Alice DEF
3 Amy GHI 789 Amy GHI
NR:当前行号
awk '{print NR,$0}' test.txt
1 ABC 123 Jack
2 DEF 456 Alice
3 GHI 789 Amy
awk '{print NR,$0,$NR}' test.txt
1 ABC 123 Jack ABC
2 DEF 456 Alice 456
3 GHI 789 Amy Amy
wc -l test.txt //wc -l显示行数
3 test.txt
awk 'END{print NR}' test.txt
3
FNR:不同文件分别计数
FILENAME:显示当前文件名
awk '{print FNR,$0}' test.txt z.txt
1 ABC 123 Jack
2 DEF 456 Alice
3 GHI 789 Amy
1 ABC:123:Jack
2 DEF:456:Alice
3 GHI:789:Amy
awk '{print FILENAME,FNR,$0}' test.txt z.txt
test.txt 1 ABC 123 Jack
test.txt 2 DEF 456 Alice
test.txt 3 GHI 789 Amy
z.txt 1 ABC:123:Jack
z.txt 2 DEF:456:Alice
z.txt 3 GHI:789:Amy
2.自定义变量
(1)使用-v来自定义变量
(2)在awk中直接定义
awk 'BEGIN{v=11;print v}'
五.格式化中,awk使用printf时需要注意的问题
1.使用printf输出的文本不会换行,使用'\n'转义换行
2.使用printf输出时,指定的格式与被格式化的文本之间要用‘,’隔开
3.使用printf输出时,格式中格式替换符必须与被格式化的文本一一对应
awk '{printf "%.2f\n",$2}' test.txt
123.00
456.00
789.00
六.awk中的pattern模式
当awk进行逐行处理时,会把pattern作为条件,判断当前行是否满足条件,若匹配则进行后面的处理,否则跳过该行。
awk 'NR==3{print}' test.txt//输出第三行的内容
七.关系运算符
< <= > >= == !=
~匹配
!~ 不匹配
八.条件判断
if(条件)
{}
else if()
{条件}
else
{}
九.循环语句
while(条件)
{}
for(变量 in 数组)
{}
for(变量;条件;表达式)
{}
do
{}
while(条件)
awk分析nginx日志
$1 IP
$4 时间
$7 url
$9 状态码
awk '{print $9}' weibo.log | sort | uniq -c//先对日志统计下状态码的分布
506 200
99 302
5 403
7 404
38 500
awk '{a[$9]++} END {for(i in a){print i,a[i]}}' weibo.log | sort -k2 -nr//对日志统计状态码分布
200 506
302 99
500 38
404 7
403 5
awk '$9==500||$9==403{print}' weibo.log | head -n 2//分析nginx日志,打印状态码500 403的前两条记录
统计日志中访问最多的10个IP
awk '{print $1}' weibo.log | sort | uniq -c | sort -k1 -nr|head -n10
awk '{a[$1]++} END for(i in a){print a[i],i|"sort -k1 -nr|head -n10"}' weibo.log
统计日志中访问大于100次的IP
awk '{a[$1]++} END{for(i in a){if(a[i]>100) print i,a[i]}}' weibo.log
统计某一天内访问最多的10个IP
awk '$4>="[9/Apr/2016:00:00:01" && $4<="[9/Apr/2016:23:59:59" {a[$1]++}END{for(i in a)print a[i],i|"sort -k1 -nr|head -n10"}' weibo.log
统计当前时间前一分钟的访问数
date=$(date -d '-1 minute' +%d/%b%Y:%H:%M);awk -vdate=$date '$4>="["date":00" && $4<="["date":59"{c++}END{print c}' weibo.log
统计访问最多的前10个页面
awk '{a[$7]++} END for(i in a){print a[i],i|"sort -k1 -nr|head -n10"}' weibo.log
统计每个IP访问状态码数量
awk '{a[$1" "$9]++} END {for(i in a){print i,a[i]}}' weibo.log
统计状态码为404的IP及出现次数
awk '{if($9~/404/a[$1" "$9]++) END {for(i in a){print i,a[i]}}}' weibo.log
awk '{if($9~/404|403/a[$1" "$9]++) END {for(i in a){print i,a[i]}}}' weibo.log