文本三剑客之AWK

awk简介

AWK是一种优良的文本处理工具。它不仅是 Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。这种编程及数据操作语言(其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母)的最大功能取决于一个人所拥有的知识。AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符进程控制语句甚至于内置的变量和函数。它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言, 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

awk是一个强大的文本分析工具,与grep(查找)、sed(编辑)一并称为“文本处理三剑客”。awk最强大的功能是对数据分析并生成报告。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk是AWK的GNU版本。

工作原理

第一步:执行BEGIN{action;… }语句块中的语句

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这 个过程,直到文件全部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;…}语句块

BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个 可选的语句块,比如变量初始化、打印输出表格的表头等语句通常 可以写在BEGIN语句块中

END语句块在awk从输入流中读取完所有的行之后即被执行,比如 打印所有行的分析结果这类信息汇总都是在END语句块中完成,它 也是一个可选语句块

pattern语句块中的通用命令是最重要的部分,也是可选的。如果 没有提供pattern语句块,则默认执行{ print },即打印每一个读取 到的行,awk读取的每一行都会执行该语句块

分割符、域和记录

awk执行时,由分隔符分隔的字段(域)标记$1,$2..$n称 为域标识。$0为所有域,注意:和shell中变量$符含义不同

文件的每一行称为记录

省略action,则默认执行 print $0 的操作

步骤

  1. 执行BEGIN{action;…}
    BEGIN在输入之前执行,通常用来打印表头,变量初始化。

  2. 读取,执行pattern{action;…}
    默认执行{ print }

  3. 执行END{action;…}
    读取到打印结束后执行,通常用作分析结果,信息汇总

AWK语法基本格式:

基本格式:awk [options] 'program' file…

选项[options]:

-F 指明输入时用到的字段分隔符

-v var=value: 自定义变量

-f:调用awk脚本

program:pattern{action statements;..}

语句之间用分号分割

pattern和action:

pattern:部分决定动作语句何时触发及触发事件 BEGIN,END  (触发条件)

action statements:对数据进行处理,放在{}内指明 print, printf  (对数据处理动作)

program通常是被单引号或双引号中

知识点整理

1、print

要点:

(1) 逗号分隔符

(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、 变量或awk的表达式

(3) 如省略item,相当于print $0

示例:

[root@centos7 ~]# tail -3 /etc/fstab #源文件
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0[root@centos7 ~]# tail -3 /etc/fstab |awk '{print}'
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0
[root@centos7 ~]# tail -3 /etc/fstab |awk '{print "wang"}'
wang
wang
wang[root@centos7 ~]# tail -3 /etc/fstab |awk '{print $0}'
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0
[root@centos7 ~]# tail -3 /etc/fstab |awk '{print $2$4}'
/appdefaults
/bootdefaults
swapdefaults、[root@centos7 ~]# tail -3 /etc/fstab |awk '{print $2,$4}'
/app defaults
/boot defaults
swap defaults[root@centos7 ~]# tail -3 /etc/fstab |awk '{print $2"\t"$4}'
/appdefaults
/bootdefaults
swapdefaults

2、变量

2.1    内建命令

FS:输入字段分隔符,默认为空白字符

~]# awk -v FS=: '{print $1,FS,$3}' /etc/passwd
~]# awk -F":" '{print $1,$3}' /etc/passwd

OFS:输出字段分隔符,默认为空白字符

 ~]# awk -v FS=":" -v OFS=: '{print $1,$3,$7 }' /etc/passwd

RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效

~]# awk -v RS=''^C{print}' /etc/passwd

ORS:输出记录分隔符,输出时用指定符号代替换行符

~]#awk -v RS=' ' -v ORS=' ' ‘{print }’ /etc/passwd

ARGC:命令行参数的个数

~]# awk -F: ‘{print NF}’ /etc/fstab,引用内置变量不用$
~]# awk -F:  '{print $(NF-1)}'  /etc/passwd

ARGV:数组,保存命令行给定的各参数

~]# [root@centos7 ~]# awk -F: '{print NF}' /etc/passwd
7
7
~]# awk -F: '{print $(NF-1)}' /etc/passwd
/root
/bin

NF:字段数量

~]#~]# awk '{print NR}' /etc/fstab ; awk END'{print NR}' /etc/fstab

NR:行号

~]# awk {print NR}' /etc/fstab /etc/fatab

FNR:个文件分别计数,行号

~]#awk {print FNR}' /etc/fstab /etc/fatab

FILENAME:当前文件名

~]# awk '{print FILENAME}' /etc/fstab
/etc/fstab
/etc/fstab

ARGC:命令行参数的个数

~

]# awk '{print ARGC}' /etc/fstab /etc/inittab ~]# awk 'BEGIN{print ARGC}' /etc/fstab /etc/inittab

ARGV:数组,保存的是命令行所给定的各参数

~]# awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/inittab
awk~]# awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/inittab
/etc/fstab~]# awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/inittab
/etc/inittab
~]# awk 'BEGIN{print ARGV[3]}' /etc/fstab /etc/inittab #没有索引为空

2.2    自定义变量

选项位置定义:-v var=hello

在program中定义:awk ‘BEGIN{test=”hello”;print test}’

示例:

[root@centos7 ~]# awk -v test='hello gawk' '{print test}' /etc/fstab
hello gawk
hello gawk
hello gawkroot@centos7 ~]# awk -v test='hello gawk' 'BEGIN{print test}' /etc/fstab
hello gawk[root@centos7 ~]# awk 'BEGIN{r=test="hello,gawk";print test}' /etc/fstab
hello,gawk[root@centos7 ~]# awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
root male
bin male 18
daemon male 18[root@centos7 ~]# cat awk.txt #脚本实现awk输出
{print script,$1,$2}
[root@centos7 ~]# awk -F: -f awk.txt txt="awk" /etc/passwd   #-f调用swk脚本root xbin x

3、   printf命令

格式化输出:printf “FORMAT”, item1, item2, ...

(1) 必须指定FORMAT

(2) 不会自动换行,需要显式给出换行控制符,\n

(3) FORMAT中需要分别为后面每个item指定格式符

print不需要指定,printf需要指定format

printf后面的字串需要使用双引号

字串定义后的内容需要使用”,”分隔,后面直接跟Item1,item2….

format用于指定后面的每个item的输出格式

printf语句不会自动打印换行符\n

格式符

%s: 显示字符串

%d,%i: 显示十进制整数

%e,%E: 科学计数法数值显示

%f: 显示为浮点数

%g,%G: 以科学数法或浮点形式显示数值

%c: 显示字符的ASCII码

%u: 无符号整数

%%: 显示%号自身,相当于转义

修饰符

N: 显示宽度

-: 左对齐(默认为右对齐)

+: 显示数值符号

示例:

[root@centos7 ~]# awk -F: '{printf"%s",$1}' /etc/passwd
rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftpnobodysystemd-networkdbuspolkitdabrtlibstoragemgmtrpccolordsaslauthrtkitchronyqemutssusbmuxdgeocluerpcusernfsnobodyradvdsetroubleshootpulsegdmgnome-initial-s[root@centos7 ~]# awk -F: '{printf"%s\n",$1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator[root@centos7 ~]# awk -F: '{printf"%-20s %10d\n",$1,$3}' /etc/passwd
root                          0
bin                           1
daemon                        2
adm                           3
lp                            4[root@centos7 ~]# awk -F: '{printf"%-20.2s %10d\n",$1,$3}' /etc/passwd
ro 0
bi 1
da 2[root@centos7 ~]# awk -F: '{print "username:%s\n",$1}' /etc/passwd
username:%sroot
username:%sbin[root@centos7 ~]# awk -F: '{printf "username:%s,UID:%d\n",$1,$3}' /etc/passwd
username:root,UID:0
username:bin,UID:1
username:daemon,UID:2
username:adm,UID:3
username:lp,UID:4
username:sync,UID:5[root@centos7 ~]# awk -F: '{printf "username:%15s,UID:%d\n",$1,$3}' /etc/passwd
username:           root,UID:0
username:            bin,UID:1
username:         daemon,UID:2          #%15s 右对齐
username:            adm,UID:3[root@centos7 ~]# awk -F: '{printf "username:%-15s,UID:%d\n",$1,$3}' /etc/passwd
username:root           ,UID:0
username:bin            ,UID:1
username:daemon         ,UID:2          #%-15s 左对齐
username:adm            ,UID:3[root@centos7 ~]#  awk -F: '{printf "username:%-20s salary:%-10.2f shell:%s\n",$1,$3,$7}' /etc/passwd
username:root                 salary:0.00       shell:/bin/bash
username:bin                  salary:1.00       shell:/sbin/nologin
username:daemon               salary:2.00       shell:/sbin/nologin
username:adm                  salary:3.00       shell:/sbin/nologin
username:lp                   salary:4.00       shell:/sbin/nologin
username:sync                 salary:5.00       shell:/bin/sync
username:shutdown             salary:6.00       shell:/sbin/shutdown
username:halt                 salary:7.00       shell:/sbin/halt

4、操作符

算数操作符

x+y, x-y, x*y, x/y, x^y, x%y

-x: 转换为负数 +x: 转换为数值

字符串操作符:没有符号的操作符,字符串连接

赋值操作符

=, +=, -=, *=, /=, %=, ^=,++, —

比较操作符

==, !=, >, >=, <, <=

模式匹配符

~:左边是否和右边匹配包含!~:是否不匹配

示例:计算1加到100和为多少[root@centos7 ~]# echo {1..100}|tr " " + |bc
5050[root@centos7 ~]# for ((sum=0,i=1;i<=100;i++));do let sum+=i;done;echo $sum
5050[root@centos7 ~]# awk BEGIN'{for(i=1;i<=100;i++){sum+=i};print sum}'
5050[root@centos7 ~]# awk BEGIN'{i=1;while (i<=100) {sum+=i;i++};print sum}'
5050
计算1加到100奇偶数和
#100以内偶奇数相加之和
[root@centos6 ~]# awk BEGIN'{sum=0;for(i=1;i<=100;i++){if(i%2==0){continue};sum+=i};print sum}'
2500#100以内偶数相加之和
[root@centos6 ~]# awk BEGIN'{sum=0;for(i=1;i<=100;i++){if(i%2==1){continue};sum+=i};print sum}'
2550
#列出十以内的奇数
[root@centos6 ~]# seq 10 |awk '{if($1%2==0){next};print $1}'
1
3
5
7
9
#列出十以内的偶数
[root@centos6 ~]# seq 10 |awk '{if($1%2!=0){next};print $1}'
2
4
6
8
10[root@centos7 ~]# awk -F: '$0 ~ /root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologinroot@centos7 ~]# awk -F: '$0 ~ /root/{print $1}' /etc/passwd
root
operator[root@centos7 ~]# awk -F: '$0 ~ /^root/' /etc/passwd
root:x:0:0:root:/root:/bin/bash[root@centos7 ~]# awk -F: '$0 !~ /root/' /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
.......[root@centos7 ~]# awk -F: '$3==0' /etc/passwd
root:x:0:0:root:/root:/bin/bash

性能比较

[root@centos7 ~]# time(seq –s ”+” 1000000|bc)  #bc运算
seq: invalid floating point argument: –s
Try 'seq --help' for more information.
real    0m0.004s
user    0m0.000s
sys 0m0.003s
[root@centos7 ~]# time(for ((i=0;i<=1000000;i++));do let total+=i;done;echo $total) #shell for运算
500000500000
real    0m7.236s
user    0m6.990s
sys 0m0.231s
[root@centos7 ~]#
[root@centos7 ~]# time(total=0;for i in {1..1000000};do total=$(($total+i));done;echo $total) #bash for运算
500000500000
real    0m7.150s
user    0m4.949s
sys 0m0.878s[root@centos7 ~]# time (awk 'BEGIN{ total=0;for(i=0;i<=1000000;i++){total+=i;};print total;}') #awk运算
500000500000
real    0m0.217s
user    0m0.092s
sys 0m0.002s

逻辑操作符

与&&,或||,非! :

示例:

[root@centos7 ~]# awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
root
bin
daemon[root@centos7 ~]# awk -F: '$3==0 || $3<=1000 {print $1}' /etc/passwd
root
bin
daemon[root@centos7 ~]# awk -F: '!($3==0) {print $1}' /etc/passwd
bin
daemon
adm[root@centos7 ~]# awk -F: '($3>=1000) {print $3}' /etc/passwd
65534
1000
1001
1002
4444[root@centos7 ~]# awk -F: '!($3>=1000) {print $1}' /etc/passwd
root
bin
daemon
adm[root@centos7 ~]# awk -F: '$3>=1000{print $1,$3}' /etc/passwd
nfsnobody 65534
li 1000
123 1001
12 1002
19 4444

函数调用: function_name(argu1, argu2, ...)

条件表达式(三目表达式):

selector?if-true-expression:if-false-expression

示例:

[

[root@centos7 ~]# awk -F: '{$3>=1000?UserType="Common User":UserType="Sysasmin or sysUser";printf "%15s: %s\n",$1,UserType}' /etc/passwdroot: Sysasmin or sysUserbin: Sysasmin or sysUserdaemon: Sysasmin or sysUseradm: Sysasmin or sysUserlp: Sysasmin or sysUsersync: Sysasmin or sysUsershutdown: Sysasmin or sysUserhalt: Sysasmin or sysUsermail: Sysasmin or sysUseroperator: Sysasmin or sysUsergames: Sysasmin or sysUserftp: Sysasmin or sysUsernobody: Sysasmin or sysUser
systemd-network: Sysasmin or sysUserdbus: Sysasmin or sysUserpolkitd: Sysasmin or sysUserabrt: Sysasmin or sysUserlibstoragemgmt: Sysasmin or sysUserrpc: Sysasmin or sysUsercolord: Sysasmin or sysUsersaslauth: Sysasmin or sysUserrtkit: Sysasmin or sysUserchrony: Sysasmin or sysUserqemu: Sysasmin or sysUsertss: Sysasmin or sysUserusbmuxd: Sysasmin or sysUsergeoclue: Sysasmin or sysUserrpcuser: Sysasmin or sysUsernfsnobody: Common Userradvd: Sysasmin or sysUsersetroubleshoot: Sysasmin or sysUserpulse: Sysasmin or sysUsergdm: Sysasmin or sysUser
gnome-initial-setup: Sysasmin or sysUsersshd: Sysasmin or sysUseravahi: Sysasmin or sysUserpostfix: Sysasmin or sysUserntp: Sysasmin or sysUsertcpdump: Sysasmin or sysUserli: Common Userapache: Sysasmin or sysUser123: Common User12: Common User19: Common User

5、PATTERN

PATTERN:根据pattern条件,过滤匹配的行,再做处理

(1)如果未指定:空模式,匹配每一行

(2) /regular expression/:仅处理能够模式匹配到的行,需要用/  /括起来

awk '/^UUID/{print $1}' /etc/fstab  仅处理匹配到的行

awk '!/^UUID/{print $1}' /etc/fstab 仅处理匹配到的行

(3) relational expression: 关系表达式,结果有“真”有“假”;结果为“真”才会被处理 ;

真:结果为非0值,非空字符串

假:结果为空字符串或0值

(4) line ranges:行范围

startline,endline:/pat1/,/pat2/    处理 pattern1 到 pattern2 之间

注意:不支持直接给出数字格式

(5) BEGIN/END模式

BEGIN{}: 仅在开始处理文件中的文本之前执行一次

END{}:仅在文本处理完成之后执行一次

示例:

[root@centos7 ~]# df #处理前显示
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda2       20961280 3750180  17211100  18% /
devtmpfs          485144       0    485144   0% /dev
tmpfs             499848       0    499848   0% /dev/shm
tmpfs             499848   19832    480016   4% /run
tmpfs             499848       0    499848   0% /sys/fs/cgroup
/dev/sda5       20961280   32948  20928332   1% /app
/dev/sda1         201380  138984     62396  70% /boot
tmpfs              99972      36     99936   1% /run/user/0
/dev/sr0         8490330 8490330         0 100% /media[root@centos7 ~]# df |grep /dev/sd |awk '{printf "DevName:%s Used:%s\n",$1,$5}'
#显示/dev/sd开头的行并对其输出显示进行优化
DevName:/dev/sda2 Used:18%
DevName:/dev/sda5 Used:1%
DevName:/dev/sda1 Used:70%[root@centos7 ~]# df | awk '$0 ~ "/dev/sd" {printf "DevName:%-10s Used:%s\n",$1,$5}'
DevName:/dev/sda2  Used:18%
DevName:/dev/sda5  Used:1%
DevName:/dev/sda1  Used:70%[root@centos7 ~]#  df |awk '$1~"^/dev/sd[[:lower:]][[:digit:]]\\>" && $5>=10 {printf "Filesystem: %-15s Used: %s\n",$1,$5}'
Filesystem: /dev/sda2       Used: 18%
Filesystem: /dev/sda1       Used: 70%[root@centos7 ~]# df |awk '/\/dev\/sd[[:lower:]][[:digit:]]\>/{if($5>10){printf "DevName:%-10s Used:%s\n",$1,$5}}'
DevName:/dev/sda2  Used:18%
DevName:/dev/sda1  Used:70%[root@centos7 ~]# awk -F: '$3<1000{print $1,$3 }' /etc/passwd
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14
nobody 99
systemd-network 192
dbus 81
polkitd 999
abrt 173
libstoragemgmt 998
rpc 32
colord 997
saslauth 996
rtkit 172
chrony 995
qemu 107
tss 59
usbmuxd 113
geoclue 994
rpcuser 29
radvd 75
setroubleshoot 993
pulse 171
gdm 42
gnome-initial-setup 992
sshd 74
avahi 70
postfix 89
ntp 38
tcpdump 72
apache 48[root@centos7 ~]# awk -F: '$NF=="/bin/bash"{print $1,NF }' /etc/passwd
#匹配最后一列为"/bin/bash",输出$1和列数NF的值
root 7
li 7
123 7
12 7
19 7[root@centos7 ~]# awk -F: '$NF=="/bin/bash"{print $1,$NF }' /etc/passwd
#匹配最后一列为"/bin/bash",输出$1和$NF变量的值
root /bin/bash
li /bin/bash
123 /bin/bash
12 /bin/bash
19 /bin/bash[root@centos7 ~]# awk -F: '$NF ~ "/bin/bash"{print $1,$NF }' /etc/passwd #
root /bin/bash
li /bin/bash
123 /bin/bash
12 /bin/bash
19 /bin/bash[root@centos7 ~]# awk -F: '$NF ~ /bash$/{print $1,$NF }' /etc/passwd
root /bin/bash
li /bin/bash
123 /bin/bash
12 /bin/bash
19 /bin/bashm[root@centos7 ~]# awk -F: '(NR<=28&&NR>=10){print $1}' /etc/passwd
operator
games
ftp
nobody
systemd-network
dbus
polkitd
abrt
libstoragemgmt
rpc
colord
saslauth
rtkit
chrony
qemu
tss
usbmuxd
geoclue
rpcuser[root@centos7 ~]# awk '/UUID/{print $1}' /etc/fstab
UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b[root@centos7 ~]# awk -F: '/^root\>/,/^ftp\>/{print $1}' /etc/passwd #root开头到ftp开头之间的行
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp[root@centos7 ~]# awk -F: 'BEGIN{print "                USER   USERID"}/^root\>/,/^ftp\>/{printf "%20s %s %-5s\n", $1,":",$3}END{print "                 end   file"}' /etc/passwd
#BEGIN指定(修饰)第一个输出,/^root\>/,/^ftp\>指定(修饰)范围第二个输出,END指定(修饰)最后一个输出范围USER   USERIDroot : 0    bin : 1    daemon : 2    adm : 3    lp : 4    sync : 5    shutdown : 6    halt : 7    mail : 8    operator : 11   games : 12   ftp : 14   end   file[root@centos7 ~]# awk -F: 'BEGIN{print "user uid \n------------------"}/^root\>/,/^ftp\>/{print $1,$3}' /etc/passwd
user uid
------------------
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14[root@centos7 ~]# awk -F: 'BEGIN{print "user uid \n------------------"}/^root\>/,/^ftp\>/{print $1,$3}END{print "==============="}' /etc/passwd
user uid
------------------
root 0
bin 1
daemon 2
adm 3
lp 4
sync 5
shutdown 6
halt 7
mail 8
operator 11
games 12
ftp 14
===============

6、常用的action

(1) Expressions:算术,比较表达式等

(2) Control statements:if, while等

(3) Compound statements:组合语句

(4) input statements

(5) output statements:print等

7控制语句

简述控制语句格式:

if(condition){statments}

if(condition){statments} else {statments}

while(condition){statments}

do {statements} while (condition)

for(expr1;expr2;expr3){statements}

break

continue

delete array [index]

delete array

exit

{statements}

7.1    if-else

语法:

if(condition){statments}

if(condition){statments} else {statments}

if(condition1){statement1}else if(condition2){statement2} else{statement3}

使用场景:对awk取得的整行或某个字段做条件判断

示例:

[root@centos7 ~]# awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
very good成绩为100;大于90打印“very good”;大于60打印“good”;其余打印“no pass”
[root@centos7 ~]# awk '{if($3>=1000){printf "Common user: %s\n",$1 } else{printf "root or sysuser : %s\n",$1}}' /etc/passwd
root or sysuser : root:x:0:0:root:/root:/bin/bash
root or sysuser : bin:x:1:1:bin:/bin:/sbin/nologin
root or sysuser : daemon:x:2:2:daemon:/sbin:/sbin/nologin
root or sysuser : adm:x:3:4:adm:/var/adm:/sbin/nologin
root or sysuser : lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
root or sysuser : sync:x:5:0:sync:/sbin:/bin/sync
root or sysuser : shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
root or sysuser : halt:x:7:0:halt:/sbin:/sbin/halt
root or sysuser : mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
root or sysuser : operator:x:11:0:operator:/root:/sbin/nologin
root or sysuser : games:x:12:100:games:/usr/games:/sbin/nologin[root@centos7 ~]# awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd
#NF字段数量,$NF表示最后字段的值,判断字段值等于/bin/bash
root
li
123
12
19[root@centos7 ~]# awk '{if(NF>5)print $0}' /etc/passwd
#NF字段数量,判断字段数大于5的行
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
[root@centos7 ~]# awk '{if(NF>5)print $0}' /etc/fstab
# Created by anaconda on Tue Jan 9 05:14:54 2018
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff / xfs defaults 0 0
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app xfs defaults 0 0
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot xfs defaults 0 0
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap swap defaults 0 0
[root@centos7 ~]# df -h |awk -F% '{print $1}'
Filesystem Size Used Avail Use
/dev/sda2 20G 3.6G 17G 18
devtmpfs 474M 0 474M 0
tmpfs 489M 0 489M 0
tmpfs 489M 20M 469M 4
tmpfs 489M 0 489M 0
/dev/sda5 20G 33M 20G 1
/dev/sda1 197M 136M 61M 70
tmpfs 98M 36K 98M 1
/dev/sr0 8.1G 8.1G 0 100[root@centos7 ~]# df -h |awk -F% '{print $1}'|awk '{print $NF}'
Use
18
0
0
4
0
1
70
1
100[root@centos7 ~]# df -h |awk -F% '/^\/dev/{print $1}'|awk '{print $NF}'
18
1
70
100#将/etc/passwd第一列当作姓名,第三列当作工资,打印报表,要求显示:
#Name:zhangsan Salary:3300 Level:High
#工资大于3000的,Level显示High,大于1000,小于等于3000的显示Soso,小于1000的显示LOW。
[root@centos7 ~]#  awk -F: '{if($3>3000){Level="High"}else if($3>1000 && $3<=3000){Level="Soso"}else{Level="Low"};printf "Name:%-20s Salary:%-20d Level:%s\n",$1,$3,Level}' /etc/passwd
Name:root                 Salary:0                    Level:Low
Name:bin                  Salary:1                    Level:Low
Name:daemon               Salary:2                    Level:Low
Name:adm                  Salary:3                    Level:Low
Name:lp                   Salary:4                    Level:Low
Name:sync                 Salary:5                    Level:Low
Name:shutdown             Salary:6                    Level:Low
Name:halt                 Salary:7                    Level:Low
Name:mail                 Salary:8                    Level:Low
Name:operator             Salary:11                   Level:Low
Name:games                Salary:12                   Level:Low
Name:ftp                  Salary:14                   Level:Low
Name:nobody               Salary:99                   Level:Low
Name:systemd-network      Salary:192                  Level:Low
Name:dbus                 Salary:81                   Level:Low
Name:polkitd              Salary:999                  Level:Low
Name:abrt                 Salary:173                  Level:Low
Name:libstoragemgmt       Salary:998                  Level:Low
Name:rpc                  Salary:32                   Level:Low
Name:colord               Salary:997                  Level:Low
Name:saslauth             Salary:996                  Level:Low
Name:rtkit                Salary:172                  Level:Low
Name:chrony               Salary:995                  Level:Low
Name:qemu                 Salary:107                  Level:Low
Name:tss                  Salary:59                   Level:Low
Name:usbmuxd              Salary:113                  Level:Low
Name:geoclue              Salary:994                  Level:Low
Name:rpcuser              Salary:29                   Level:Low
Name:nfsnobody            Salary:65534                Level:High
Name:radvd                Salary:75                   Level:Low
Name:setroubleshoot       Salary:993                  Level:Low
Name:pulse                Salary:171                  Level:Low
Name:gdm                  Salary:42                   Level:Low
Name:gnome-initial-setup  Salary:992                  Level:Low
Name:sshd                 Salary:74                   Level:Low
Name:avahi                Salary:70                   Level:Low
Name:postfix              Salary:89                   Level:Low
Name:ntp                  Salary:38                   Level:Low
Name:tcpdump              Salary:72                   Level:Low
Name:li                   Salary:1000                 Level:Low
Name:apache               Salary:48                   Level:Low
Name:123                  Salary:1001                 Level:Soso
Name:12                   Salary:1002                 Level:Soso
Name:19                   Salary:4444                 Level:High

7.2    while循环

语法:while(condition){statments}

意义:条件”真”,进入循环;条件”假”,退出循环

使用场景:对于行内的多个字段逐一类似处理时使用,对数组中的个元素逐一处理时使用。

[root@centos7 ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $1,length($i);i++}}' /etc/grub2.cfg
linux16 7
linux16 30
linux16 46
linux16 2
linux16 4
linux16 5
linux16 16
linux16 7
linux16 50
linux16 46
linux16 2
linux16 4
linux16 5[root@centos7 ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=40){print $1,length($i)};i++}}' /etc/grub2.cfg
#以空白符开头后跟”linux16″的行中,把字符数大于40的字符串打印出来。
linux16 46
linux16 50
linux16 46

7.3    do-while循环

语法:do {statements} while (condition)

    (无论真假,至少执行一次循环体 )

示例:

[root@centos7 ~]# seq 3|awk 'BEGIN{i=1;print i++,i}'
#i的值:先输出i的值,在做(加法)运算
1 2
[root@centos7 ~]# seq 3|awk 'BEGIN{i=1;print ++i,i}'
#i的值:先做(加法)运算,在输出i 的值
2 2
[root@centos7 ~]# awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}'
#累加运算:计算0-100之和
5050

7.4    for循环

语法:for(expr1;expr2;expr3) {statement;…}

常见用法:for(variable assignment;condition;iteration process) {for-body}

特殊用法:

能够遍历数组中的元素

语法:for(var in array) {for-body}

示例:

[root@centos7 ~]#  awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print$i,length($i)}}' /etc/grub2.cfg
#遍历:统计以linux16开头的行各字符串出现次数
linux16 7
/vmlinuz-3.10.0-693.el7.x86_64 30
root=UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff 46
ro 2
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
/vmlinuz-0-rescue-ff4aa58d9e1f44f7b7aae5f6fd1a3242 50
root=UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff 46
ro 2
rhgb 4
quiet 5

7.5    switch语句

语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}

7.6    break和continue

break [n]

continue [n]

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}’

7.7    net

提前结束对本行处理而直接进入下一行处理(awk自身循环)

示例:

[root@centos7 ~]# awk -F: '{if($3%2!=0)  print $1,$3}' /etc/passwd
root 0
daemon 2
lp 4
shutdown 6
mail 8
games 12
ftp 14
systemd-network 192
libstoragemgmt 998
rpc 32
saslauth 996
rtkit 172
geoclue 994
nfsnobody 65534
gdm 42
gnome-initial-setup 992
sshd 74
avahi 70
ntp 38
tcpdump 72
li 1000
apache 48
12 1002
[root@centos7 ~]# seq 20 | awk -F: '{if($1%2==0)next ; print $1}'
#打印奇数行;匹配$1%2取余数的等于0的结束循环
1
3
5
7
9
11
13
15
17
19

8、array(数组 )

关联数组:array[index-expression]

index-expression:

(1) 可使用任意字符串;字符串要使用双引号括起来

(2) 如果某数组元素事先不存在,在引用时,awk会自动创建 此元素,并将其值初始化为“空串”

若要判断数组中是否存在某元素,要使用“index in array”格 式进行遍历

若要遍历数组中的每个元素,要使用for循环;

for(var in array) {for-body}

注意:var会遍历array的每个索引;

state["LISTEN"]++

state["ESTABLISHED"]++

9、函数

数值处理:

rand():返回0和1之间一个随机数

[root@centos7 ~]# awk 'BEGIN{srand();print int(rand()*100)}'
#随机一个两位数的整数,*100
71

字符串处理:

length([s]):返回指定字符串的长度

sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹 配的内容替换为s

[root@nanyibo ~]# echo "2018:3:30 17:38:30" |awk 'sub(/:/,"-",$1)'
2018-3:30 17:38:30

gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换 为s所表示的内容

[root@nanyibo ~]# echo "2018:3:30 17:38:30" |awk 'gsub(/:/,"-",$1)'
2018-3-30 17:38:30

split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存 至array所表示的数组中,第一个索引值为1,第二个索引值为2,…

netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++} END{for (i in count) {print i,count[i]}}'
#先进行分割,取出第五列对第五列做分割取出以分隔符:的第一列,设置变量count索引为ip[1]做加法运算,只输出一次结果。

自定义函数

格式:

function name ( parameter, parameter,  ... ) { statements return expression }

示例:

#cat fun.awk function max(v1,v2) { v1>v2?var=v1:var=v2return var}
BEGIN{a=3;b=2;print max(a,b)}
#awk –f fun.awk

示例:

[root@nana ~]# cat  fi.txt
1 2 3 4 5 6 7 8 9 10
11 12 12 14 15 16 17 18 19 20
[root@nana ~]# awk '{i=1;sum=0;while(i<=NF){sum+=$i;i++};print sum}' f1.txt 显示每行各自的总行
55
155
[root@nana ~]# awk '{i=1;while(i<=NF){sum+=$i;i++};print sum}' f1.txt 每行显示一次总和
55
210
[root@nana ~]# awk '{i=1;while(i<=NF){sum+=$i;i++}}END{print sum}' f1.txt 只显示总和
210

对十以内整数奇数输出jishu,偶数输出偶数

效果如下:

1 jishu

2 oushu

3 jishu

[root@centos7 /]# echo {1..10} |awk '{i=1;while(i<=NF){if($i%2==0){print $i,"is oushu"} else{print $i, "is jishu"};i++}}'
1 is jishu
2 is oushu
3 is jishu
4 is oushu
5 is jishu
6 is oushu
7 is jishu
8 is oushu
9 is jishu
10 is oushu
[root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
Tuesday
Monday
[root@centos7 ~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i] ,i}}'
#i的值为每次数组weekdays的索引,这个过程称为遍历
Tuesday tue
Monday mon

函数统计类型出现次数

~]# netstat -tan |awk '/^tcp\>/{state[$NF]++}END{for (i in state){ print i,state[i]}}'
#函数state中下标为$NF的值:LISTEN和ESTABLISHED,他们的值做++运算,
#END{}:仅在文本完成之后执行一次,后边for循环只做一次,
#i变量的值为:数组state的下标,也就是:LISTEN和ESTABLISHED。
#print i的值为for训话i的值,就是$NF的值:LISTEN和ESTABLISHED。
#state[i]的值为,END前边完成时的值++的相加之和,
#也就是state数组的值:state[LISTEN]=3和state[ESTABLISHED]=1
LISTEN 8
ESTABLISHED 3

显示/bash类型次数

[root@centos7 ~]# awk -F: '{shell[$7]++}END{for(n in shell){print n,shell[n]}}' /etc/passwd
/bin/sync 1
/bin/bash 5
/sbin/nologin 36
/sbin/halt 1
/sbin/shutdown 1

统计http日志文件,IP地址访问次数

[root@centos7 ~]# awk '{ip[$1]++}END{for(i in ip){print i ,ip[i]}}' /var/log/httpd/access_log172.18.253.55 1788
172.18.251.122 52
172.18.251.150 34
172.18.251.141 30
172.18.251.160 157
172.18.251.170 457
172.18.251.107 14
172.18.251.109 51
172.18.251.145 50
172.18.0.223 12
172.18.253.21 74087
::1 15
172.18.251.147 354
172.18.254.78 183
172.18.251.157 330
172.18.252.134 514
172.18.251.149 158
172.18.254.6 1643
172.18.250.183 81
172.18.251.21 81
172.18.254.34 659

awk实现取出从定向

[root@centos7 ~]# awk -F: '! shell[$7]++' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/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

去重

[root@centos6 ~]#awk -F: '!shell[$0]++' /etc/passwd #去重

统计/etc/fstab文件中每个文件系统类型出现的次数;

#源文件
[root@centos7 ~]# awk '/^UUID/{print $0}' /etc/fstab
UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff /                       xfs     defaults        0 0
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e /app                    xfs     defaults        0 0
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c /boot                   xfs     defaults        0 0
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b swap                    swap    defaults        0 0[root@centos7 ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
swap 1
xfs 3

统计指定文件中每个单词出现的次数;

[root@centos7 ~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
UUID=c424d9be-be2c-4e7c-a007-1af750d9310b 1
Tue 1
man 1
and/or 1
UUID=0cd9ec5d-a77e-46f4-b218-19d914a5ed1e 1
maintained 1
xfs 3
Accessible 1
# 7
are 1
defaults 4
Jan 1
blkid(8) 1
/ 1
0 8
See 1
Created 1
05:14:54 1
on 1
mount(8) 1
9 1
anaconda 1
UUID=3535b5f0-7b38-4cc9-a099-551fa388392c 1
fstab(5), 1
/app 1
/boot 1
findfs(8), 1
2018 1
'/dev/disk' 1
by 2
/etc/fstab 1
pages 1
more 1
info 1
swap 2
filesystems, 1
reference, 1
UUID=24d11781-1f0f-4fe5-805c-6ca807fd24ff 1
for 1
under 1

脚本实现AWK

system命令

空格是awk中的字符串连接符,如果system中需要使用awk中 的变量可以使用空格分隔,或者说除了awk的变量外其他一律 用""引用起来。

awk BEGIN'{system("hostname") }' awk 'BEGIN{score=100; system("echo  your score is " score) }'

[root@nanyibo ~]# cat awk.txt
function max(v1,v2){v1>v2?var=v1:var=v2return var
}
BEGIN{print max(a,b)}
[root@nanyibo ~]# awk -v a=30 -v b=20 -f awk.txt
30
[root@nanyibo ~]# awk -v a=10 -v b=20 -f awk.txt
20

将awk程序写成脚本,直接调用或执行

示例:

#cat f1.awk {if($3>=1000)print $1,$3}
#awk -F: -f f1.awk /etc/passwd
#cat f2.awk #!/bin/awk –f #this is a awk script {if($3>=1000)print $1,$3}
#chmod +x f2.awk
#f2.awk –F:  /etc/passwd

向awk脚本传递参

格式:

awkfile  var=value var2=value2... Inputfile

注意:在BEGIN过程中不可用。直到首行输入完成以后,变 量才可用。可以通过-v 参数,让awk在执行BEGIN之前得到 变量的值。命令行中每一个指定的变量都需要一个-v参数

示例:

#cat  test.awk   #!/bin/awk –f {if($3 >=min && $3<=max)print $1,$3}
#chmod +x test.awk
#test.awk -F: min=100 max=200  /etc/passwd

文本三剑客之AWK详解相关推荐

  1. Linux文本三剑客之一——awk详解(1)——awk看这两篇就够啦~PS:文末有练习,来练练手吧

    shell编程三剑客 grep --> egrep --> 文本过滤 查询 awk 文本截取 sed  文本的替换和修改 目录 awk awk也可以做小数运算 awk命令简要处理流程 aw ...

  2. Linux三剑客之awk详解

    第一篇 awk简介与表达式实例 一种名字怪异的语言 模式扫描和处理,处理数据和生成报告. awk不仅仅是linux系统中的一个命令,而且是一种编程语言:它可以用来处理数据和生成报告(excel):处理 ...

  3. Linux命令:文本处理工具awk详解

    awk命令简介: awk是一个强大的文本分析工具,通常,awk是以文件的每一行,为处理单位的.awk每接收文件的一行,然后执行相应的命令,来处理文本.  1.命令格式: awk 'pattern {a ...

  4. 文本处理工具AWK详解

    awk简介 awk: 中文意思是报告生成器 能够根据我们输入的信息,将信息格式化以后显示,将定义好的信息以比较美观(直观)的方式显示出来出现比较早,继而出现了new awk(nawk)在windows ...

  5. php 字符流在linux,PHP_linux正则表达式awk详解,awk和sed一样是流式编辑器,它 - phpStudy...

    linux正则表达式awk详解 awk和sed一样是流式编辑器,它也是针对文档中的行来操作的,一行一行的去执行.awk比sed更加强大,它能做到sed能做到的,同样也能做到sed不能做到的.awk常用 ...

  6. python实现文本编辑器_Python实现文本编辑器功能实例详解

    这篇文章主要介绍了Python实现的文本编辑器功能,结合实例形式详细分析了基于wxpython实现文本编辑器所需的功能及相关实现技巧,需要的朋友可以参考下 本文实例讲述了Python实现的文本编辑器功 ...

  7. android中的TextView组件,Android-TextView文本视图控件详解

    TextView是Android开发当中运用到最多的控件之一,显示一行或者多行文本,也可以给上下左右设置图片,并且结合SpannableString和其子类可以做到图文混排. TextView文本视图 ...

  8. python中choices_Django之choices选项和富文本编辑器的使用详解

    项目准备 1.创建数据库 create database choices_test default charset utf8; 2.创建一个名为 choices_test 的Django项目: 3.创 ...

  9. Linux文本编译工具VIM详解

    Linux文本编译工具VIM详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.VIM概述 1>.vim简介 1>.vi: 全称Visual editor,即文本编 ...

最新文章

  1. 巧用宏定义进行调试 (转)
  2. 从零到两百台服务器的创业野蛮生长史
  3. [Office 2010 易宝典]怎样直接将Office文档保存为PDF格式?
  4. java hasmoreelements_Java IOException.hasMoreElements方法代码示例
  5. redis存opc_KEPServerEX6完整免费版
  6. C++11 并发指南六(atomic 类型详解一 atomic_flag 介绍)
  7. richtextbox自动滚动到最下面_Axure RP 9教程:banner轮播最简单的实现方法
  8. Docker虚拟机理论
  9. 《网络工程师考试 考前冲刺预测卷及考点解析》复习重点
  10. qiniu rs.php,七牛API操作类 - suconghou的个人空间 - OSCHINA - 中文开源技术交流社区...
  11. Debian8.1 安装samba与windows共享文件,在系统重启后samba服务无法自动启动
  12. 阿里云播放器直播rtsp、rtmp、flv流,flash播放直播流
  13. Java实战之管家婆记账系统(24)——项目总结
  14. JAVA 中字符串的长度
  15. 菲尼克斯电源维修QUINT4-UPS/24DC/24DC
  16. ApacheCN 活动汇总 2019.7.27
  17. 【新解】多品种小批量时代下,工业企业的成本核算方法
  18. Python将头像照片转换为漫画,采用GAN深度学习,无噪点
  19. 常见的传输介质及其特性
  20. 小车红外线自主充电方案-1

热门文章

  1. 006.尚学堂阶段1_简单错误如何处理_守破离学习法_程序员修炼手册
  2. 【Zynq UltraScale+ MPSoC】基于LWIP模板的udp通信与测试(二):PL与PS基于BRAM的UDP通信
  3. 行人检测系统中的行人特征及检测方法
  4. 一个数的亲和数iiic++_小学1-6年级数学公式和定律
  5. 使用ESP8266-01s连接阿里云并发送数据
  6. 七星彩长奖表图_2018够力七星彩奖表
  7. ABAP 如何发布odata服务
  8. 带你轻松写出第一篇优秀论文
  9. PRML翻译 Chap1 Introduction
  10. Oracle 漏洞修复方案