awk命令详解
awk 是一种编程语言,用于在linux/nuix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大的编程工具。它在命令行中使用,但更多是作为脚本来使用。
awk 的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一个字母。因为它的作者是三个恩,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
awk命令两种使用方式:
(1)命令行模式:awk [options] ‘commands’ file(s)
(2)脚本模式:awk [options] -f scriptfile file[s]
awk 命令模式
awk [options] ‘commands’ file(s)
option:
-F 定义字段分割符号
-v 定义变量并赋值
command:
1、范围说明或者正则表达式或者{awk命令语句1;awk命令语句2;}
2、范围说明部分可以是BEGIN、END、逻辑表达式或者为空
3、awk命令语句间用分号间隔
4、引用shell变量时需要用双引号引起,命令模式都在单引号’'里面
BEGIN{} {} END{}
行处理前 行处理 行处理后
字段分割及相关变量
$1,$2,$3...$n:awk中用该顺序形式表示files中每行以间隔符号分割的各列的不同字段
$0 表示文本本身
NF 表示当前记录的字段数(列数)
$NF 最后一列
$(NF-1) 倒数第二列
FNR/NR 行号
FILENAME 文件名
"\t" 制表符
RS 换行符
"" 打印字符串
FS 定义间隔符
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
/[0-9][0-9]+/ 两个或两个以上数字
-F'[:#/]' 定义三个分隔符
awk –F: '{print $1,$3,$7}' /etc/passwd
awk '{print NR}' /etc/fstab ; awk END '{print NR}' /etc/fstab
awk -F:'{print $(NF-1)}' /etc/passwd
格式化输出:
%c:显示字符的ASCII码
%d, %i:显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
awk -F: '{printf "%s",$1}' /etc/passwd
awk -F: '{printf "%s\n",$1}' /etc/passwd
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %s\n",$1}' /etc/passwd
awk -F: '{printf “Username: %s,UID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %15s,UID:%d\n",$1,$3}' /etc/passwd
awk -F: '{printf "Username: %-15s,UID:%d\n",$1,$3}' /etc/passwd
awk模式和动作
任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态。
模式可以是:正则表达式、比较表达式、条件表达式、算术运算符、逻辑操作符和复合模式、范围模式等。
正则表达式
匹配字段:匹配操作符(~ !~)
awk '/^UUID/{print $1}' /etc/fstab
awk '!/^UUID/{print $1}' /etc/fstab
行范围
awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd
awk -F: ‘(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
条件表达式:
awk -F: '$3>300 {print $0}' /etc/passwd
awk -F: '{ if($3>300) print $0 }' /etc/passwd
awk -F: '{ if($3>300) {print $0} }' /etc/passwd
awk -F: '{ if($3>300) {print $3} else{print $1} }' /etc/passwd
算术运算:+ - * / % ^
awk -F: '$3 * 10 > 500' /etc/passwd
逻辑操作符:与&&,或||,非!
awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
awk -F: '!($3==0) {print $1}' /etc/passwd
awk -F: '!($3>=500) {print $3}' /etc/passwd
条件表达式(三目表达式) selector?if-true-expression:if-false-expression
awk脚本
awk控制语句if-else
awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF>=80{print $1,$5}'
while循环
awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10){print $i,length($i)}; i++}}' /etc/grub2.cfg
for循环
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
数组
netstat -tan | awk '/^tcp/{state[$NF]++} END{for(i in state) { print i,state[i]}}'
awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
函数
rand():返回0和1之间一个随机数
awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
cat fun.awk
function max(x,y)
{
x>y?var=x:var=y
return var
}
BEGIN{a=3;b=2;print max(a,b)}
awk -f fun.awk
综合练习
查找netstat -nt命令的结果中Foreign Address列的地址,统计每个地址链接的次数,如果⼤于2次,显⽰ip
netstat -nt |awk '/^tcp/{print $5}'|awk -F: '{print $1}'|sort |uniq -c|awk '$1>1{print $2}'
172.18.116.232
模拟并发访问http服务,查找ip连接次数超过200次的访问ip地址 模拟并发
yum -y install httpd-tools
ab -c 10 -n 200 http://172.18.120.26/
显⽰超过200次访问的ip:
awk '{print $1}' /var/log/httpd/access_log|sort|uniq -c
awk '{print $1}' /var/log/httpd/access_log|sort|uniq -c|awk '$1>200{print $2}'
显⽰磁盘使⽤率⼤于等于8%的分区
df -h|awk -F% '/^\/dev/{print $1}'| awk '$NF>=8{print $1,$5}'
查找连接本机的次数⼤于20的ip地址,加⼊到防⽕墙禁⽌连接
ss -nt | awk -F'[ :]+' '!/State/{ip[$(NF-2)]++}END{for(i in ip){print i,ip[i]}}' | while read line; do ip=`echo $line | awk '{if($2>20)print $1}'`;[ -z "$ip" ] || iptables -A INPUT -s $ip -j REJECT; done
解决DOS攻击⽣产案例:根据web⽇志或⽹络连接数,监控当某个ip并发连接 数或者短时间内pv达到100,即调⽤防⽕墙命令封掉对应的ip,监控频率每隔5分 钟;防⽕墙命令为iptables -A INPUT -s IP -j REJECT
while true ;do
awk '/^[0-9]/{IP[$1]++}END{for(i in IP){if (IP[i]>=100)print i}}' /var/log/httpd/access_log | while read line;do iptables -A INPUT -s $line -j REJECT;done
sleep 300 done
使⽤netstat和awk统计服务器出现tcp⽹络状态并按数量排序?
netstat -tan |grep "^tcp\b" |awk '{print $5}' |sort | uniq -c| sort -nr