awk高级用法

编写awk脚本

打印hello world的几种方式

[root@localhost ~]# echo | awk '{print "hello world"}'
hello world
[root@localhost ~]# echo -e " \n \n" | awk '{print "hello world"}'
hello world
hello world
hello world

[root@localhost ~]# cat a
hello ,world
[root@localhost ~]# awk '{print}' a
hello ,world

打印文件的第一列

[root@c2 ~]# awk -F: '{print $1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt

没有对像操作

awk中只能用双引号

结构: begin(不需要对象可以处理) 主体(写到主体必须要有对象) end(归纳)

[root@localhost ~]# awk 'BEGIN{print "hello world"}'
hello world

[root@localhost ~]# cat kk
hello,world

hello

hi
[root@localhost ~]# vi kk
[root@localhost ~]# awk '/^$/{print "This is ablank line."}' kk
This is ablank line.
This is ablank line.
This is ablank line.
This is ablank line.

[root@c2 ~]# awk 'BEGIN{print}/^$/{print "This is ablank line."}' kk

This is ablank line.
This is ablank line.
This is ablank line.
This is ablank line.

字段和引用的分离

awk 允许使用字段操作符$来指定字段

$1: 表示第一段

$2: 表示第二段

$0: 表示整个字段

[root@localhost ~]# awk '{print $1,$2,$3}' ll
jerry thistest 888-999-000
[root@localhost ~]# awk '{print $1$2$3}' ll
jerrythistest888-999-000
[root@localhost ~]# awk '{print $1":"$2":"$3}' ll
jerry:thistest:888-999-000

[root@localhost ~]# awk '{print $0}' ll
jerry thistest 888-999-000

一行中调换位置顺序

[root@localhost ~]# cat ll
jerry thistest 888-999-000
[root@localhost ~]# awk '{print $3,$1,$2}' ll
888-999-000 jerry thistest


用awk计算数字
加 、减 、 乘 、除 、取余

[root@localhost ~]# echo a b c d | awk 'BEGIN{one=1;two=2}{print $(one+two)}'
c
[root@localhost ~]# awk 'BEGIN{print 1+2}'
3
[root@localhost ~]# awk 'BEGIN{print 4/10}'
0.4
[root@localhost ~]# awk 'BEGIN{print 4*10}'
40
[root@localhost ~]# awk 'BEGIN{print 2**2}'
4
[root@localhost ~]# awk 'BEGIN{print 10%2}'
0

-F: 改变字段的分隔符,而不只是用数字和变量

\t: 表示一个实际的制表符的转义序列

[root@localhost ~]# awk -F'\t' '{print $1}' ll
jerry thistest
[root@c2 ~]# awk -F'\t' '{print $1}' ll
jerry thistest 888-999-000

[root@localhost ~]# awk -F'\t\n' '{print $1}' ll
jerry thistest	 888-999-000

FS: 可以通过FS来改变字段分隔符

[root@c2 ~]# awk -F'\t' '{print $2}' ll
888-999-000

[root@c2 ~]# awk 'BEGIN{FS="\t"}{print $2}' ll
888-999-000

不同表示之间的区别:

FS = “\t” : 将每个制表符作为一个字段分隔符

FS = “ \t++” : 表示用一个或多个制表符来分隔字段

FS = “ [ \t]” : 使用一个正则表达式指定几个字段为分隔符

取出ip地址: 两种方式

[root@c2 ~]# ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens160:  mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:a4:aa:a2 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.136.140/24 brd 192.168.136.255 scope global dynamic noprefixroute ens160
       valid_lft 1281sec preferred_lft 1281sec
    inet6 fe80::20c:29ff:fea4:aaa2/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

[root@c2 ~]# ip a | grep 'inet ' | grep -v '127' | awk '{print $2}' | awk -F'/' '{print $1}'
192.168.136.140


[root@localhost ~]# ip a | grep 'inet ' | grep -v '127' | awk  -F '[ /]+' '{print $3}'
192.168.136.136
[root@localhost ~]# 

表达式:

序列 描述
\a 报警字符,通常时ASC|| BEL 字符
\b 退格键
\f 走字符
\n 换行符
\r 回车
\t 水平分割线
\v 垂直分割线
\ddd 将字符表示为1到3为八进制
\xbex 将字符表示为十六进制值
\c 任何需要字面表示的字符c

变量是引用值的标识符

定义变量(只能由数字、字母、下划线,但不能以数字开头)

[root@localhost ~]# awk 'BEGIN{a= "hello" "world"} {print a}' a
helloworld
[root@localhost ~]# awk 'BEGIN{a= "hello"" ""world"} {print a}' a
hello world
[root@localhost ~]# awk 'BEGIN{a= "hello world"} {print a}' a
hello world

算术操作符

操作符 描述
+
-
*
/
% 取模
^ && ** 取幂
[root@localhost ~]# awk 'BEGIN{print 2^4}'
16
[root@localhost ~]# awk 'BEGIN{print 2**4}'
16
[root@localhost ~]# awk 'BEGIN{x=1;y=x+1}{print y}' a
2

操作符 定义
++ 变量加1
变量减1
+= 将加的结果赋给变量
-= 将减的的结果赋给变量
*= 将乘的的结果赋给变量
/+ 将除的的结果赋给变量
%= 将取模的的结果赋给变量
^= 和 **= 将取幂的的结果赋给变量

统计空行数

[root@localhost ~]# cat kk
hello,world

hello

hi


[root@localhost ~]# awk '/^$/{print x+=1}' kk (x 没有定义的时候默认为0)
1
2
3
4

区别:

++x(先加在打印)

x ++ (先打印再加)

[root@localhost ~]# awk '/^$/{print ++x}' kk 
1
2
3
4
[root@localhost ~]# awk '/^$/{print x++}' kk
0
1
2
3

在主体里面运算完之后在结果里面打印

[root@localhost ~]# awk '/^$/{++x}END{print x}' kk
4

平均值

[root@localhost ~]# cat ss
jerry 90 89 80 87 88 67
sairr 90 80 90 90 90 90
gerrt 98 98 90 97 70 80
[root@localhost ~]# awk '{total=$2+$3+$4+$5+$6;avg=total/5;print $1, avg }' ss
jerry 86.8
sairr 88
gerrt 90.6

[root@localhost ~]# cat ss
jerry 90 89 80 87 88 67
sairr 90 80 90 90 90 90
gerrt 98 98 90 97 70 80
[root@localhost ~]# awk -F'90' '{print $1}' ss
jerry 
sairr 
gerrt 98 98 
[root@localhost ~]# cat ss
jerry 	90 89 80 87 88 67
sairr 90 80 90 90 90 90
gerrt 98 98 90 97 70 80
[root@localhost ~]# awk '{print $1}' ss
jerry
sairr
gerrt
[root@localhost ~]# awk -F'\t' '{print $1}' ss
jerry 
sairr 90 80 90 90 90 90
gerrt 98 98 90 97 70 80

OFS: FS 等效的输出OFS,它的默认值为一个空格

[root@localhost ~]# cat ss
jerry 	90 89 80 87 88 67
sairr 90 80 90 90 90 90
gerrt 98 98 90 97 70 80
[root@localhost ~]# awk 'BEGIN{FS= " "}{print $1,$3}' ss
jerry 89
sairr 80
gerrt 98
[root@localhost ~]# awk 'BEGIN{FS= " ";OFS=":"}{print $1,$3}' ss
jerry:89
sairr:80
gerrt:98
[root@localhost ~]# awk 'BEGIN{FS= " ";OFS=":"}{print $1 $3}' ss
jerry89
sairr80
gerrt98
[root@localhost ~]# head /etc/passwd | awk 'BEGIN{FS=":";OFS="-"}{print $1,$3}'
root-0
bin-1
daemon-2
adm-3
lp-4
sync-5
shutdown-6
halt-7
mail-8
operator-11

POSIX 增加了一个新的变量CONVFMT,它用来控制数字到字符串的转换

[root@localhost ~]# awk 'BEGIN{print 5.5+2.4 " is a test."}'
7.9 is a test.

NR : 行号

[root@c2 ~]# ip a | grep 'inet ' | awk -F'[ /]+' 'NR==2{print $3}'
192.168.136.140

NF: 列数

$NF: 打印最后一列

[root@localhost ~]# awk '{print NF}' ss
7
7
7
[root@localhost ~]# awk '{print $NF}' ss
67
90
80

打印倒数第一行

[root@localhost ~]# cat ss
jerry 	90 89 80 87 88 67
sairr 90 80 90 90 90 90
gerrt 98 98 90 97 70 80
[root@localhost ~]# awk '{print $(NF-1)}' ss
88
90
70
[root@c2 ~]# df -Th
Filesystem          Type      Size  Used Avail Use% Mounted on
devtmpfs            devtmpfs  351M     0  351M   0% /dev
tmpfs               tmpfs     370M     0  370M   0% /dev/shm
tmpfs               tmpfs     370M  5.4M  365M   2% /run
tmpfs               tmpfs     370M     0  370M   0% /sys/fs/cgroup
/dev/mapper/cs-root xfs        17G  6.9G   11G  41% /
/dev/sda1           xfs      1014M  226M  789M  23% /boot
tmpfs               tmpfs      74M     0   74M   0% /run/user/0
[root@c2 ~]# 
[root@c2 ~]# df -h | awk 'NR==1{print $(NF-1),$NF}NR!=1{print $NF}'
Mounted on
/dev
/dev/shm
/run
/sys/fs/cgroup
/
/boot
/run/user/0

处理多行记录

RS

ORS

[root@localhost ~]# awk 'BEGIN{FS="\n";RS=":"}{print $1,$NF}' ll
jerry thistest	 888-999-000 
[root@localhost ~]# awk 'BEGIN{FS="\n";RS="";OFS="\n";ORS="\n\n"}{print $1,$NF}' ll
jerry thistest	 888-999-000
jerry thistest	 888-999-000

[root@localhost ~]# awk 'BEGIN{FS="\n";RS=""}{print $1,$NF}' ll
jerry thistest	 888-999-000 jerry thistest	 888-999-000

支票簿结算

[root@localhost ~]# cat bb
1000
125 Marhet -125.45
126 Jerry -89.3
127 kkkkd -79.2
128 xxich -50.2
129 hshdv -88.9
[root@localhost ~]# awk 'NR==1{print "begin balance:\t" $1 }' bb
begin balance:	1000
[root@localhost ~]# awk 'NR==1{print "begin balance:\t" $1;balance=$1;next}{print $1,$2,$3}' bb
begin balance:	1000
125 Marhet -125.45
126 Jerry -89.3
127 kkkkd -79.2
128 xxich -50.2
129 hshdv -88.9
[root@localhost ~]# 

[root@localhost ~]# awk 'NR==1{print "begin balance:\t" $1;balance=$1;next}{print $1,$2,$3;print balance+=$NF}' bb
begin balance:	1000
125 Marhet -125.45
874.55
126 Jerry -89.3
785.25
127 kkkkd -79.2
706.05
128 xxich -50.2
655.85
129 hshdv -88.9
566.95

关系操作符和布尔操作符

操作符 描述
< 小于
== 相等的
> 大于
<= 小于等于
>= 大于等于
!= 不等的
~ 匹配
!- 不匹配

布尔操作符

操作符 定义
|| 逻辑或
&& 逻辑与
逻辑非

例:

NF == 6 && NR > 1

打印文件的大小和名字

[root@localhost ~]# ll | awk 'NR!=1{printf "%d\t%s",$5,$9}'
72	!13	a1336	anaconda-ks.cfg88	bb25	kk28	ll73	ss[root@localhost ~]# ll | awk 'NR!=1{printf "%d\t%s\n",$5,$9}'
72	!
13	a
1336	anaconda-ks.cfg
88	bb
25	kk
28	ll
73	ss

用filenume来累加列表中文件的数量

[root@c2 ~]# ll | awk '{sum+=$5;++filenum;print $5,"\t",$9}'
 	 
1246 	 anaconda-ks.cfg
70 	 b
125 	 bbb
104 	 c
93 	 cc
20 	 d
90 	 kk
28 	 ll
356 	 ttt
119 	 yy


[root@c2 ~]# ll | awk '{sum+=$5;++filenum;print $5,"\t",$9}END{print "Total: ",sum}'
 	 
1246 	 anaconda-ks.cfg
70 	 b
125 	 bbb
104 	 c
93 	 cc
20 	 d
90 	 kk
28 	 ll
356 	 ttt
119 	 yy
Total:  2251



[root@c2 ~]# ll | awk '{sum+=$5;++filenum;print $5,"\t",$9}END{print "Total: ",sum,"bytes"}'
 	 
1246 	 anaconda-ks.cfg
70 	 b
125 	 bbb
104 	 c
93 	 cc
20 	 d
90 	 kk
28 	 ll
356 	 ttt
119 	 yy
Total:  2251 bytes




[root@c2 ~]# ll | awk '{sum+=$5;++filenum;print $5,"\t",$9}END{print "Total: ",sum,"bytes("filenum" file)"}'
 	 
1246 	 anaconda-ks.cfg
70 	 b
125 	 bbb
104 	 c
93 	 cc
20 	 d
90 	 kk
28 	 ll
356 	 ttt
119 	 yy
Total:  2251 bytes(11 file)

[root@c2 ~]# ll | awk 'NR!=1{sum+=$5;++filenum;print $5,"\t",$9}END{print "Total: ",sum,"bytes("filenum" file)"}'
1246 	 anaconda-ks.cfg
70 	 b
125 	 bbb
104 	 c
93 	 cc
20 	 d
90 	 kk
28 	 ll
356 	 ttt
119 	 yy
Total:  2251 bytes(10 file)


格式化打印

printf 的格式说明符

字符 定义
c ASCLL 字符
d 十进制整数
i 十进制整数(在POSIX中增加的)
e 浮点格式
E 浮点格式
f 浮点格式
g e或f 的转格式,长度最短,末尾的0被去掉
G E或F 的转格式,长度最短,末尾的0被去掉
O 无符号的八进制
s 字符串
u 无符号的十六进制
x 无符号的十六进制,用a-f表示10-15
X 无符号的十六进制,用A-F表示10-15
% 字面字符%

printf (不换行)

可以格式化输出

[root@localhost ~]# awk 'BEGIN{printf "|%10s|","hello"}'
|     hello|[root@localhost ~]# 

用printf 产生一个输出,他输出不同的两个字段上的字符串和十进制
[root@localhost ~]# awk 'BEGIN{printf "|%-10s|","hello"}'
|hello     |[root@localhost ~]# 
[root@localhost ~]# awk 'BEGIN{printf "|%-10d|","100"}'
|100       |[root@localhost ~]# 

与END 在一起的用法

[root@c2 ~]# ll | awk 'BEGIN{print "bytes","\t","file"}NR!=1{sum+=$5;++filenum;print $5,"\t",$9}END{printf "Total: \t%d bytes(%d file)",sum,filenum}'
bytes 	 file
1246 	 anaconda-ks.cfg
70 	 b
125 	 bbb
104 	 c
93 	 cc
20 	 d
90 	 kk
28 	 ll
356 	 ttt
119 	 yy
Total: 	2251 bytes(10 file)[root@c2 ~]# 


while循环

[root@localhost ~]# awk 'BEGIN{do{++i;print i}while (i<=4)}'
1
2
3
4
5
[root@localhost ~]# awk 'BEGIN{do{++i;print i}while (i<4)}'
1
2
3
4
[root@localhost ~]# awk 'BEGIN{while(i<=4){print i;i++}}'

1
2
3
4
[root@localhost ~]# awk 'BEGIN{while(i<4){++i;print i}}'
1
2
3
4
[root@localhost ~]# awk 'BEGIN{while(i<=4){++i;print i}}'
1
2
3
4
5

你可能感兴趣的:(linux,服务器,运维)