【四月更文打卡】Linux文本三剑客之AWK-详细介绍(下)

105 阅读2分钟

Linux文本三剑客之AWK-详细介绍(下)

awk控制语句

{ statements;… } 组合语句 
if(condition) {statements;…}  
if(condition) {statements;…} else {statements;…} 
while(conditon) {statments;…} 
do {statements;…} while(condition) 
for(expr1;expr2;expr3) {statements;…} 
break 
continue 
delete array[index] 
delete array 
exit 

awk条件判断

  • 语法:if(condition1){statement1}else if(condition2){statement2}else{statement3}
  • 使用场景:对awk取得的整行或某个字段做条件判断
  • 示例:
awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd 
awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd 
awk '{if(NF>5) print $0}' /etc/fstab 
awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd 
awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd 
df -h|awk -F% '/^/dev/{print $1}'|awk '$NF>=80{print $1,$5}' 
awk 'BEGIN{ test=100;if(test>90){print "very good"} 
else if(test>60){ print "good"}else{print "no pass"}}' 

awk循环

while循环

  • 语法:while(condition){statement;…}
  • 条件“真”,进入循环;条件“假”,退出循环
  • 使用场景:
对一行内的多个字段逐一类似处理时使用 
对数组中的各元素逐一处理时使用 
  • 示例:
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 

do-while循环

  • 语法:do {statement;…}while(condition)
  • 意义:无论真假,至少执行一次循环体
  • 示例:
    awk ‘BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print

for循环

  • 语法:for(expr1;expr2;expr3) {statement;…}
  • 常见用法: for(variable assignment;condition;iteration process){for-body}
  • 特殊用法:能够遍历数组中的元素
  • 语法:for(var in array) {for-body}
  • 示例: awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
  • 性能比较
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)

[root@centos7 ~]#time (awk 'BEGIN{ total=0;for(i=0;i<=1000000;i++){total+=i;};print to tal;}')
500000500000

real    0m0.059s
user    0m0.051s
sys     0m0.008s
[root@centos7 ~]#time (total=0;for i in {1..1000000};do total=$(($total+i));done;echo
$total)
500000500000

real    0m4.208s
user    0m2.835s
sys     0m1.358s
[root@centos7 ~]#time (for ((i=0;i<=1000000;i++));do let total+=i;done;echo $total)
500000500000

real    0m5.108s
user    0m4.575s
sys     0m0.515s
[root@centos7 ~]#time (seq -s "+" 1000000|bc)
500000500000

real    0m0.266s
user    0m0.072s
sys     0m0.203s

switch语句

  • 语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
  • break和continue
    awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}' 
    awk ‘BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}' 
  • break [n]

  • continue [n]

  • next:提前结束对本行处理而直接进入下一行处理(awk自身循环)

    • 示例: awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

awk数组

  • awk直接使用关联数组:array[index-expression]
  • index-expression:索引表达式
(1) 索引表达式可使用任意字符串;字符串要使用双引号括起来 
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串” 
(3) 若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历 
  • 示例:
weekdays["mon"]="Monday"  
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday"; 
print weekdays["mon"]}‘ 
awk '!line[$0]++'  dupfile 
awk '{!line[$0]++;print $0, line[$0]}'  dupfile 
  • 若要遍历数组中的每个元素,要使用for循环 for(var in array) {for-body} 注意:var会遍历array的每个索引
  • 示例:
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}' 
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