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