条件判断 if-else
使用场景:对awk取得的整行或某个字段做条件判断
if(condition){statement;…}[else statement]
if(condition1){statement1}else if(condition2){statement2}else if(condition3)
{statement3}...... else {statementN}
条件判断 switch-case
awk 中的switch分支语句功能较弱,只能进行等值比较或正则匹配。 各分支结尾需使用break来终止
循环 while
条件“真”,进入循环;条件“假”,退出循环 使用场景: 对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用
循环 do-while
无论真假,至少执行一次循环体
循环 for
特殊用法:能够遍历数组中的元素
for(var in array) {for-body}
[root@ubuntu2204 ~]# awk 'BEGIN{ arr[0]=123;arr[1]=456;for(i in arr){ print
i"==>"arr[i] };}'
0==>123
计算当前文件的总和
# cat abc.txt
1 2 3 4 5
#cat abc.txt |awk '{for(i=1;i<=NF;i++){sum+=$i};print sum}'
15
#cat abc.txt|tr ' ' + |bc
15
#sum=0;for i in `cat abc.txt`;do let sum+=i;done;echo $sum
15
性能比较
time (awk 'BEGIN{ total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
time (total=0;for i in {1..10000};do total=$(($total+i));done;echo $total)
time (for ((i=0;i<=10000;i++));do let total+=i;done;echo $total)
time (seq -s"+" 10000|bc)
continue 和 break
continue 中断本次循环 break 中断整个循环
next
next 可以提前结束对本行处理而直接进入下一行处理(awk自身循环)
数组 awk的数组为关联数组
index-expression
利用数组,实现 k/v 功能
可使用任意字符串;字符串要使用双引号括起来
如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
封掉查看访问日志中连接次数超过1000次的IP
[root@ubuntu2204 ~]# awk '{ip[$1]++}END{for(i in ip){if(ip[i]>=1000)
{system("iptables
-A INPUT -s "i" -j REJECT")}}}' nginx.access.log-20200428
awk 函数 awk 的函数分为内置和自定义函数
数值处理
rand() #返回0和1之间一个随机数
srand() #配合rand() 函数,生成随机数的种子
int() #返回整数
字符串处理
str1=(str2,str3) #连字符,字符串拼接
length([s]) #返回指定字符串的长度
sub(r,s,[t]) #在t中串搜索r匹配的内容,并将第一个匹配内容替换为s
gsub(r,s,[t]) #在t中串搜索r匹配的内容,并将匹配内容全部替换为s,即贪婪模式
split(s,array,[r]) #以r为分隔符,切割串s,并将结果保存至array数组中,索引值为1,2,…
统计用户名的长度
[root@ubuntu2204 ~]# cut -d: -f1 /etc/passwd | awk '{print length()}'
[root@ubuntu2204 ~]# awk -F: '{print length($1)}' /etc/passwd
调用shell命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了 awk的变量外其他一律用""引用起来
[root@ubuntu2204 ~]# awk 'BEGIN{system("hostname")}'
rocky86.m51.magedu.com
[root@ubuntu2204 ~]# awk 'BEGIN{score=100; system("echo your score is " score)
}'
your score is 100
[root@ubuntu2204 ~]# netstat -tn | awk
'/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){if(count[i]>=10)
{system("iptables -A INPUT -s "i" -j REJECT")}}}'
时间函数
time() #当前时间到1970年1月1日的秒数
strftime() #指定时间格式
[root@ubuntu2204 ~]# awk 'BEGIN{print systime()}'
1609917829
[root@ubuntu2204 ~]# awk 'BEGIN{print systime();system("date +%s")}'
1661687319
1661687319
[root@ubuntu2204 ~]# awk 'BEGIN{print strftime("%Y-%m-
%dT%H:%M",systime()-3600)}'
2021-01-06T14:24
[root@ubuntu2204 ~]# awk 'BEGIN{print strftime("%Y-%m-%d %H:%M:%S");system("date
\"+%Y-%m-%d %H:%M:%S\"")}'
2022-08-28 19:51:34
2022-08-28 19:51:34
自定义函数
function name ( parameter, parameter, ... ) {
statements
return expression
}
awk 脚本
将awk程序写成脚本,直接调用或执行
向awk脚本传递参数
awkfile var=value var2=value2... Inputfile
注意:
上面格式变量在BEGIN过程中不可用。直到首行输入完成以后,变量才可用
可以通过-v 参数,让awk在执行BEGIN之前得到变量的值
命令行中每一个指定的变量都需要一个-v参数
1.文件host_list.log 如下格式,请提取”.magedu.com”前面的主机名部分并写入到回到该文件中
1 www.magedu.com
2 blog.magedu.com
3 study.magedu.com
4 linux.magedu.com
5 python.magedu.com
......
999 study.magedu.com
参考答案
[root@ubuntu2204 ~]# awk -F'[ .]' '{print $2}' host_list.log >> host_list.log
[root@ubuntu2204 ~]# cat host_list.log
1 www.magedu.com
1 www.magedu.com
2 blog.magedu.com
3 study.magedu.com
4 linux.magedu.com
5 python.magedu.com
......
999 study.magedu.com
www
blog
study
linux
python
2.统计/etc/fstab文件中每个文件系统类型出现的次数
参考答案:
[root@rocky86 ~]# awk -F' +' '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}'
/etc/fstab
swap 1
ext4 3
[root@rocky86 ~]# awk -F' +' '/^UUID/{print $3}' /etc/fstab |uniq -c
3 ext4
1 swap
3.统计/etc/fstab文件中每个单词出现的次数
参考答案;
[root@rocky86 ~]# awk -F"[^[:alpha:]]" '{for(i=1;i<=NF;i++)word[$i]++}END{for (a
in word)if(a !="") print a,word[a]}' /etc/fstab
4.提取出字符串Yd$C@M05MB%9&Bdh7dq+YVixp3vpw中的所有数字
答案:
[root@rocky86 ~]# echo 'Yd$C@M05MB%9&Bdh7dq+YVixp3vpw' | awk '{gsub(/[^0-
9]/,"");print $0}'
05973
[root@rocky86 ~]# echo 'Yd$C@M05MB%9&Bdh7dq+YVixp3vpw' |awk -F ""
'{for(i=1;i<=NF;i++){if ($i ~ /[[:digit:]]/){str=$i; str1=(str1 str)}};print
str1}'
[root@rocky86 ~]# echo 'Yd$C@M05MB%9&Bdh7dq+YVixp3vpw' | awk -F'[^0-9]'
'{for(i=1;i<=NF;i++){printf "%s",$i }}'
05973
5.文件random.txt记录共5000个随机的整数,存储的格式100,50,35,89…请取出其中最大和最小的整 数
参考答案
[root@rocky86 ~]# str="";for((i=1;i<=5000;i++));do if [ $i -ne 5000 ];then
str+="$RANDOM,";else str+=$RANDOM;fi;done;echo $str > random.txt
[root@rocky86 ~]# awk -F, '{max=$1;min=$1;for(i=1;i<=NF;i++){if($i>max)
{max=$i}else{if($i<min){min=$i}}}}END{print "最大值:"max,"最小值:"min}'
random.txt
6.解决Dos攻击生产案例:监控当某个IP并发连接数超过100时,即调用防火墙命令封掉对应的IP,监 控频率每隔5分钟。防火墙命令为:iptables -A INPUT -s IP -j REJECT
参考答案
[root@rocky86 ~]# ss -nt | awk -F " +|:" 'NR!=1{ip[$(NF-2)]++}END{for(i in ip)
{if(ip[i]>100){system("iptables -A INPUT -s "i" -j REJECT")}}}'
7.将以下文件内容中FQDN取出并根据其进行计数从高到低排序
http://mail.magedu.com/index.html
http://www.magedu.com/test.html
http://study.magedu.com/index.html
http://blog.magedu.com/index.html
http://www.magedu.com/images/logo.jpg
http://blog.magedu.com/20080102.html
http://www.magedu.com/images/magedu.jpg
参考答案;
[root@centos8 ~]#awk -F"/" '{url[$3]++}END{for(i in url){print url[i],i}}'
url.log |sort -nr
3 www.magedu.com
2 blog.magedu.com
1 study.magedu.com
1 mail.magedu.com
8.将以下文本文件awktest.txt中 以inode列为标记,对inode列相同的counts列进行累加,并且统计出 同一inode中,beginnumber列中的最小值和endnumber列中的最大值
inode|beginnumber|endnumber|counts|
106|3363120000|3363129999|10000|
106|3368560000|3368579999|20000|
310|3337000000|3337000100|101|
310|3342950000|3342959999|10000|
310|3362120960|3362120961|2|
311|3313460102|3313469999|9898|
311|3313470000|3313499999|30000|
311|3362120962|3362120963|2|
输出的结果格式为:
106|3363120000|3368579999|30000|
310|3337000000|3362120961|10103|
311|3313460102|3362120963|39900|
参考答案:
[root@centos8 ~]#cat awktest.txt
inode|beginnumber|endnumber|counts|
106|3363120000|3363129999|10000|
106|3368560000|3368579999|20000|
310|3337000000|3337000100|101|
310|3342950000|3342959999|10000|
310|3362120960|3362120961|2|
311|3313460102|3313469999|9898|
311|3313470000|3313499999|30000|
311|3362120962|3362120963|2|
[root@rocky86 ~]# awk -F '|'
'!/^inode/{sum[$1]+=$4;if(!begin[$1])begin[$1]=$2;else
if(begin[$1]>$2)begin[$1]=$2;if(!end[$1])end[$1]=$3;else if(end[$1]
<$3)end[$1]=$3}END{for(i in sum)print i"|"begin[i]"|"end[i]"|"sum[i]}'
awktest.txt
[root@rocky86 ~]# awk -F'|' -v OFS='|' '/^[0-9]/{inode[$1]++; if(!bn[$1])
{bn[$1]=$2}else if(bn[$1]>$2){bn[$1]=$2}; if(en[$1]<$3)en[$1]=$3;cnt[$1]+=$(NF1)} END{for(i in inode)print i,bn[i],en[i],cnt[i]}' awktest.txt
以上存是个人笔记 不喜勿喷 谢谢