前言
awk的中有很多的控制语句,awk也支持if语句,while语句,for语句等等编程逻辑充的控制语句及数组、函数。
awk的进阶无非就是多练。
1.控制语句
(1)if-else语句
语句格式: if(condition) {statments} if (条件) 条件为真 执行{statments}
只有一个语句可以省略{}。组合语句必须加{}if(condition) {statments} else {statements}双分支语句 if(条件)为真时执行{statments} else否则执行{statrments}
例:显示系统上某个用户的ID号大于1000,这是普通用户,反之则为系统用户
~]# awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
(提示: -F: 是以:为分隔符 $3/etc/passwd 是第三段 printf 格式化输出 $1/etc/passwd 的第一段 另外这是空模式是每一行都读取的)
例 显示shell为/bin/bash的用户
~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
( 提示NF是字段数 -F:分隔符:)
显示/etc/fstab 的一行字段数大于五个 ,否则不显示
~]# awk '{if(NF>5) print $0}' /etc/fstab
(提示:NF是字段数 $本身 也就是取过来的行整行)
显示磁盘使用的使用率到5%的分区。
~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=5) print $1}'
(提示: -F[%]是以空格分隔 /^\/dev/ 是以/dev/开头 也就是地址定界。 $NF是取末尾的字段数)
对awk取得的整行或某个字段做条件判断;
(2) while循环
语法:while(condition) statement
条件“真”,进入循环;条件“假”,退出循环;
while(conditon) {statments} 只有一个语句可以省略{}。组合语句必须加{}
while使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用;
显示每一个符合条件的行,行内的每一个字段,字段本身和字段的个数。条件(统计/etc/grub,conf 以空白开头后跟kernel的行)
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub.conf
(提示: /^[[::space:]]*kernel/ 以有多个空白的行后跟kernel做地址定界 i=1:知道变量i=1 i<=NF是判断有多少个字段数 NF是字段数,print $i 是显示第几个字段数 , length()内建函数 :返回指定字符串的长度; i++自加 不然都是1了)
把字符数小于7的不予显示
awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {if(length($i)>=7){print $i,length($i)}; i++}}' /etc/grub.conf
(3)do-while循环
语法:do statement while(condition)
意义:不管是真是假先执行一遍。至少执行一次循环体
(4) for循环
语法: for(expr1;expr2;expr3) {statements}
expr1 初始化;expr2条件判断;expr3控制变量不断的修正
for(variable assignment;condition;iteration process) {for-body}
~]# awk '/^[[:space:]]*kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
显示每一个符合条件的行,行内的每一个字段,字段本身和字段的个数。条件(统计/etc/grub,conf 以空白开头后跟kernel的行)(跟上面差不多 ,只不过是采用for循环)
特殊用法:
能够遍历数组中的元素;
语法:for(var in array) {for-body}
(5) switch语句
语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement}
这个语法意思: 表达式: case value1 值跟表达式匹配 或者是 正则表达式跟表达式匹配。则显示statment 。。。。。。。默认用default:statement
(6) break和continue
break [n] 跳出N层循环
continue 退出本次循环
(7)next
提前结束对本行的处理而直接进入下一行;这是跟break不一样的 ,next直接进入下一行的,break是进入下一字段的。
显示ID为偶数的用户
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
(提示 $3%2!=0 next ID号不等于0 直接跳入下一行 )
2.array(数组)
关联数组:array[index-expression]在awk 使用最多
index-expression:
delete array[index] 从数组中删除某个元素
delete array 删除整个数组
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
weekdays[mon]="Monday"
例: awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}
它会显示那个呢; 你在去掉mon 和tue的双引号 看看会怎么言
若要遍历数组中的每个元素,要使用for循环;
for(var in array) {for-body}
例:awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
(提示: 定义一个数组weekdays )
注意:var会遍历array的每个索引;
state["LISTEN"]++
state["ESTABLISHED"]++
显示netstat -tan 的以tcp开头的状态,并做统计
~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
(提示: '/tcp\>/做地址定界, state[]数组 )
~]#awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
练习1:统计/etc/fstab文件中每个文件系统类型出现的次数;
~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
(提示:‘/^UUID’地址定界 fs[]数组 )
练习2:统计指定文件中每个单词出现的次数;
~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
(提示 :count[]是数组 )
3.函数
(1)内置函数
数值处理:
rand():返回0和1之间一个随机数;
字符串处理:
length([s]):返回指定字符串的长度;
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
(2)自定义函数
想加强sed和awk可以看《sed和awk》
原创文章,作者:N19_king,如若转载,请注明出处:http://www.178linux.com/20275