Linux三剑客之AWK
工作原理
# awk -F: '{print $1,$3}' /etc/passwd
1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束。
2)然后,行被:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始,最多达100个字段。
3)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕。
语 法
==command(时空)
BEGIN{} {} END{} :
- BEGIN{} begin发生在行处理前(注意大写);
- {} 行处理时,读一行执行一次;
- END{} 行处理后。
例:
# awk 'BEGIN{print 1/2}{print "-----";print $0}END{print "HOHO"}' /etc/hosts
0.5
-----
127.0.0.1 localhost localhost.localdomain localhost4
localhost4.localdomain4
-----
::1 localhost localhost.localdomain localhost6
localhost6.localdomain6
HOHO
内部变量:
- F****S :输入字段分隔符(默认空格) # awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd | head -1;
- OFS :输出字段分隔符 # awk -F: 'BEGIN{FS=":";OFS="+++"}{print $1,$2,$3,$4}' /etc/passwd root+++x+++0+++0;
- RS :输入记录(行)分隔符,默认换行符。请注意,在此时记录已经不是行的概念了。分隔符由”换行符“换成了”空格“;
- ORS :输出记录(行)分隔符,默认换行符;
- FNR :多文件独立编号;
- NR :多文件汇总编号;
- NF :字段总数 # awk -F: '{print NF, $0}' /etc/passwd。
格式化输出
1. print 函数
[root@localhost ~]# awk -F: '{print "username is: " $1
"\t uid is: " $3}' /etc/passwd | head -1
username is: root uid is: 0
2. printf 函数
- %s 字符类型;
- %d 数值类型;
- %f 浮点型,可以定义保留;
- 占15字符;
- - 表示左对齐,默认是右对齐;
- printf默认不会在行尾自动换行,加\n;
- , 逗号,输出字段分隔符。
模式和动作
1. 概念
任何awk语句都由模式和动作组成。
- 模式部分决定动作语句何时触发及触发事件。
- 如果省略模式部分,动作将时刻保持执行状态。每一行都会有动作。
- 模式可以是任何条件语句或复合语句或正则表达式。
- 有模式的话,就是对模式对应的行进行动作。
2. 字符串比较
# awk '/^root/' /etc/passwd
# awk '$0 ~ /^root/' /etc/passwd
# awk '$0!~/^root/' /etc/passwd
# awk -F: '$1 ~ /^root/' /etc/passwd
3. 数值比较
3.1 目的
比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。
3.2 关系运算符
1)语法
运算符 含义 示例:
- < 小于 x<y
- <= 小于或等于 x<=y
- == 等于 x==y
- != 不等于 x!=y
- >= 大于等于 x>=y
- > 大于 x>y
2)示例
# awk -F: '$3 == 0' /etc/passwd
# awk -F: '$3 == 1' /etc/passwd
# awk -F: '$3 < 10' /etc/passwd
== 也可以用于字符串判断
# awk -F: '$7 == "/bin/bash"' /etc/passwd
# awk -F: '$1 == "alice"' /etc/passwd
3.3 算术 运算
1)语法
+ - * / %(模) (幂23)
2)示例
# awk -F: '$3 * 10 > 500' /etc/passwd
4. 多条件
1)逻辑操作符和复合模式
语法:
- && 逻辑与 a&&b
- || 逻辑或 a||b
- ! 逻辑非 !a
例:
# awk -F: '$1~/root/ && $3<=15' /etc/passwd
# awk -F: '$1~/root/ || $3<=15' /etc/passwd
# awk -F: '!($1~/root/ || $3<=15)' /etc/passwd
2)范围模式
语法:
awk '/从哪里/,/到哪里/' filename。
例:
# awk -F: '/adm/,/lpd/' /etc/passwd
从adm到ldp,显示出来,注意避免匹配重复的字段。
AWK脚本编程
1. 变量
1)自定义内部变量
awk -v user=root -F: '$1 == user' /etc/passwd
-v定义变量。
2)外部变量
双引号:
# var="bash"
# echo "unix script" | awk "{print "123",\"$var\"}"
123 bash
注意:awk调用外部变量时,外部使用双引号,内部也使用双引号,但需要转义内部的双引号。
单引号:
# var="bash"
# echo "unix script" |awk '{print $1,"'"$var"'"}'
unix bash
注意:使用单引号时,内部需要用双引转义。
2. 条件&判断
1)if语句
格式:{if(表达式){语句;语句;...}}
2)if...else语句
格式:
- {if(表达式){语句;语句;...}else{语句;语句;...}}
- {if(){}else
3)if...else if...else语句
格式:
- if (条件){动作}elseif(条件){动作}else
- if(){}else if (){}else if(){}else{}
例:
- 题目:统计出三种用户的数量;
- 管理员数量:管理员ID为0;
- 内置用户数量:用户ID<1000;
- 普通用户数量:用户ID>999。
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
3. 循环
1)while
- 循环打印10个数字 awk 'BEGIN{ while(i<=10){print i; i++} }'
- 每行打印十次 awk -F: '{ while(i<=9) {print $0; i++}}' passwd
2)for
- 循环打印5个数字:awk 'BEGIN{for(i=1;i<=5;i++){print i} }'
- 将每行打印10次:awk -F: '{ for(i=1;i<=10;i++) {print $0} }' /etc/passwd
- 打印每一行的每一列:awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd
4. 数组
1)定义数组
将用户名定义为数组的值,打印第一个值。
# awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd
2)数组遍历
- 按索引遍历:
# awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd
- 按元素遍历(了解):
awk -F: '{username[x++]=$1} END{for(i=0;i<x;i++) print i,username[i]}' /etc/passwd
5. awk编程案例
1)统计/etc/passwd中各种类型shell的数量
awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }' /etc/passwd
2)统计Apache/Nginx日志中的访问前十 <统计日志>
cat access_log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn |head
浙公网安备 33010602011771号