awk
报告生成器,格式化文本输出
- 文本处理
- 输出格式化的文本报表
- 执行算数运算
- 执行字符串操作
常用动作
打印动作,可自动换行
$0 表示当前行,$1,$2.$3…第几列
{}中不加“”会认为是变量,加双引号会认为是字符
默认分隔符是空格和tab键,不限数量 -F 指定分隔符 [] 括号里可指定多个分隔符
-v 变量赋值,不加的话在BEGIN中不起作用
常用变量
- FS=“:” 输入指定:为分隔符,赋予变量
- OFS=‘+++’ 指定输出的分隔符
- RS=‘;’ 输入指定分隔符
- ORS=‘+’ 输出时用+替换换行符,默认为换行符
- NF 不用赋值,指每一行的所有字段数量, N F 为最后一列的值, NF 为最后一列的值, NF为最后一列的值,(NF-1)倒数第二列
- NR 行号,多个文件每个文件独立行号加个F,FNR,默认多个文件会合并行号
- FILENAME 文件名
[root@rocky8 ~]#awk -v class="48" 'BEGIN{print class;class="49";print class}'
48
49
[root@rocky8 ~]#cat test.txt
a,b,c;1,2,3;x,y,z
[root@rocky8 ~]#awk -v RS=";" -v FS="," '{print $1}' test.txt
a
1
x
#取文件相对应字符再写入原文件
[root@rocky2 ~]#awk -F"[. ]" '{print $2}' hosts.txt >>hosts.txt
printf动作
- 必须指定FORMAT(格式)
- 不会自动换行,需要显式给出换行控制符 \n
- FORMAT中需要分别为后面每个item指定格式符
常用格式
%c:显示字符的ASCII码
%d, %i:显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
修饰符
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度, #如:%3.1f
- 左对齐(默认右对齐) #如:%-15s
+ 显示数值的正负符号 #如:%+d
比较符,条件判断
==, !=, >, >=, <, <=
执行条件
格式可写 // &&并且 ||或者 !取反
#举例
[root@rocky2 ~]#seq 10 | awk 'i=!i'
1
3
5
7
9
[root@rocky2 ~]#awk '/^b/,/^h/' /etc/passwd #查找开头行
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
- BEGIN{}:仅在开始处理文件中的文本之前执行一次
- END{}:仅在文本处理完成之后执行一次
条件判断
if-else
#对变量score赋值判断区间80以上,60到80,60以下,并执行相对应区间的指令
[root@rocky2 ~]#awk 'BEGIN{score=88;if(score>=80){print "good"}else if(score>=60){print "pass"}else{print "no pass"}}'
[root@rocky2 ~]#cat score.txt
name score
wei 90
wang 77
li 55
[root@rocky2 ~]#awk 'NR!=1{score=$2;if(score>=80){print $1,"good"}else if(score>=60){print $1,"pass"}else{print $1,"no pass"}}' score.txt
文件n.txt有一行数字,计算其总和
[root@rocky2 ~]#cat n.txt
1 2 3 4 5
tr ' ' + < n.txt|bc
sum=0;for i in `cat n.txt` ;do let sum+=i;done;echo $sum
awk '{sum=0;for(i=1;i<=NF;i++){sum+=i};print sum}' n.txt
数组
实现只打印出现一次的值,即去重,第一次出现会赋予值1并打印且++,后续再出现就是++的值,!取反都为0,不打印
awk '!line[$0]++' file
具体
[root@rocky2 ~]#cat test.txt
a
b
c
a
b
c
a
b
e
a
[root@rocky2 ~]#awk '!line[$0]++' test.txt
a
b
c
e
结合for循环
for循环刷完全部数组的元素出现次数
$1第一列的值作为数组的下标
ss -ant|awk 'NR>=2{state[$1]++}END{for(i in state){print state[i],i}}'
函数
#可调用shell命令
system("xx")
awk 'BEGIN{system("hostname")}'
自定义函数function
[root@rocky2 ~]#cat func.awk
function max(x,y) { #定义函数max,x和y相当于位置变量参数,占位用
x>y?var=x:var=y
return var
}
BEGIN{print max(a,b)} #调用函数,a和b相当于$x和$y
[root@rocky2 ~]#awk -v a=30 -v b=20 -f func.awk #a和b赋值,-f调用文件
30
举例:取域名出现次数
[root@rocky2 ~]#cat url.txt
http://mail.magedu.com/index.html
http://www.magedu.com/test.html
http://study.magedu.com/index.html
http://blog.magedu.com/index.html
http://www.magedu.com/images/logo.jpg
http://blog.magedu.com/20080102.html
http://www.magedu.com/images/magedu.jpg
[root@rocky2 ~]#awk -F'/' '{url[$3]++}END{for(i in url){print url[i],i}}' url.txt|sort -rn
3 www.magedu.com
2 blog.magedu.com
1 study.magedu.com
1 mail.magedu.com