shell

shell.4.3 GNU-awk(进阶1–action中的控制语句)

 

导语:
=============

awk–ACTION中的控制语句:

if(condition)  {statements}
if(condition)  {statements}  else  {statements}

while(condition)  {statements}

do{statements}  while (condition)           “do-while”循环:不管条件是真是假,先执行一次循环体;

for(控制变量初始化;条件判断表达式;控制变量的修正语句) {statements}
for(var  in  array)  {statements}

break
continue
next
exit

delete  array[index]
delete  array

备注:statements如果是组合语句,需要用花括号;

目录:
==============
1、if-else条件判断
2、while循环
3、do-while循环
4、for循环
5、switch条件判断语句
6、循环语句的跳出动作
7、next
8、awk的数组
9、awk的函数

正文:
=====================

1、if-else条件判断

语法:if(condition) {statement1} [else {statement2}]

备注:如果是单分支的if语句,”statement1″的花括号可以省略;如果是双分支的if语句,则”statement1″和”statement2″都需各自加上花括号;

使用场景:对awk取得的整行或某个字段做条件判断;

~]# awk  -F:  ‘{if($3>=1000) print  $1,$3}’  /etc/passwd
~]# awk  -F:  ‘{if($NF==”/bin/bash”) printf   “%-18s:%-10s:%-s\n”,$1,$3,$7}’   /etc/passwd
~]# awk  -F:  ‘{if($3>=1000) {printf  “common user : %-18s:%-s\n”,$1,$3}  else  {printf   “system user : %-18s:%-s\n”,$1,$3}}’   /etc/passwd

2、while循环

语法:while(condition) {statements}
条件为”真”,进入循环;条件为”假”,退出循环;

使用场景:对一行内的多个字段逐一进行类似处理时使用;对数组中的各元素逐一处理时使用;

~]# awk  ‘/^[[:space:]]*linux16/{i=1;while(i<=NF)  {printf  “%-55s,%-s\n”,$i,length($i);i++}}’  /etc/grub2.cfg
~]# awk  ‘/^[[:space:]]*linux16/{i=1;while(i<=NF)  {printf  “%-55s,%-s\n”,$i,length($i);i++}}’  /etc/grub2.cfg  |  awk  -F,   ‘{if($2>10)printf   “%-55s,%-s\n”,$1,$2}’
~]# awk  ‘/^[[:space:]]*linux16/{i=1;while(i<=NF)  {if(length($i)>10) {printf   “%-55s,%-s\n”,$i,length($i)};i++}}’  /etc/grub2.cfg

3、do-while循环

语法:do{statements} while (condition)

4、for循环

语法:for(控制变量初始化;条件判断表达式;控制变量的修正语句) {statements}

for循环在awk中的特殊应用:遍历数组元素;
语法:for(var in array) {statements}

~]#  awk  ‘/^[[:space:]]*linux16/{for(i=1;i<=NF;i++)  {if(length($i)>10){printf   “%-55s,%-s\n”,$i,length($i)}}}’   /etc/grub2.cfg

5、switch条件判断语句

语法
switch(expression)  {case  value1  or  /regexp1/:  statement1;  case  value2  or  /regexp2/:  statement2;  …;  default:  statement}

判断”expression”表达式是否等于”value1″,或者是否跟”/regexp1/”模式相匹配,如果等于”value1″或者跟”/regexp1/”匹配,则执行”statement1″;
如果第一条case语句判断结果是”否”,则执行第二条case语句,依次类推;
如果所有的case语句判断结果都是”否”,则执行默认的语句”default: statement”;

注意:如果case中的”statement”是符合语句,则需使用花括号;

使用场景:通常用作字符串比较判断;

6、循环语句的跳出动作
循环语句的动作对象是文本行的各个字段;

break  [n] :  跳出当前循环或跳出第n轮循环;

continue :   跳出当前循环,进入下一个循环(进入下一个字段的处理)

7、next

awk命令自身会对文本内容基于行为单位从第一行开始一直到最后一行的循环;
如果awk命令中带有对字段处理的循环语句,则awk里面有2个循环体;

“next”的作用是:提前结束对当前行的处理,而直接进入对下一行的处理;

~]#  awk   -F:  ‘{if($3%2==0)  printf   “%-18s:%-s\n”,$1,$3}’   /etc/passwd
~]#  awk   -F:  ‘{if($3%2!=0)  next;  printf   “%-18s:%-s\n”,$1,$3}’   /etc/passwd

8、awk的数组

关联数组格式:array[index-expression]

index-expression:
1> 可使用任意字符串;字符串要使用””双引号;比如,weekdays[“mon”]=”Monday”;
2> 如果某属组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为”空字符串”;

若要判断数组中是否存在某元素,要使用”index in array”格式;

要遍历数组中的每个元素,要使用for循环;
语法格式:for(var in array)  {statements}

“var”会遍历”arry”的每个索引;

~]#  awk  ‘BEGIN{weekdays[“mon”]=”monday”;weekdays[“tue”]=”tuesday”;  for(w  in  weekdays)  print  weekdays[w]}’

~]#  netstat  -tan  |  awk   ‘/^tcp\>/{state[$NF]++} END {for(i  in  state)  {print   i, state[i]}}’

~]#  awk  ‘{ipaddr[$1]++} END {for(count  in  ipaddr)  {print  ipaddr[count],count}}’    access_2018-03-14.log  |  sort  -nr  |  head  -15
~]#  cat   access_2018-03-14.log  |  cut  -d’ ‘  -f1  |  sort  |  uniq  -c  |  sort  -rn  |  head  -15

~]#  awk   ‘{for(i=1;i<=NF;i++){count[$i]++}} END {for(w  in  count) {printf   “%-5s,%-s\n”, count[w],w}}’    /etc/fstab

9、awk的函数

awk有内置函数,也可以自定义函数;

内置函数:
1> 数值处理
rand()    :    返回0和1之间的随机数;第一次取出的数值是随机数,如果后续不做其他处理动作,此随机数会保持不变;

[root@KOU ~]# 
[root@KOU ~]# awk 'BEGIN{print rand()}'
0.237788
[root@KOU ~]# awk 'BEGIN{print rand()}'
0.237788
[root@KOU ~]# awk 'BEGIN{print rand()}'
0.237788
[root@KOU ~]#

2> 字符串处理
length(s) :       返回指定字段的字符串长度;”s”表示某行的某个字段;
sub(r,s,[t]) :     r表示某个模式,以这个模式去匹配查找t所表示的字符串,并将其第一次匹配到的内容替换为s所表示的内容;
gsub(r,s,[t]) :    r表示某个模式,以这个模式去匹配查找t所表示的字符串,并将其所有匹配到的内容替换为s所表示的内容;

split(s,a[,r]) :     以r为分隔符切割字符串s,并将切割后的结果保存至a所表示的数组中;数组的索引下标数从1开始计算;

~]#  netstat  -tan  |  awk   ‘/^tcp\>/{split($5,ip,”:”); count[ip[1]]++} END {for(i  in  count) {print  count[i],i}}’

Leave a Reply

Your email address will not be published. Required fields are marked *