awk - pattern scanning and processing language
基本用法:gawk [option] 'program' FILE ... program: PATTERN{ACTION STATEMENTS} 语句之间用分号分隔 print,printf 选项: -F: 指明输入时用到的分隔符: -v var=value 自定义变量:
1、 print
print item1, item2, ...
要点:
(1)逗号分隔符:
(2)输出的各item可以字符串,也可以是数值:当前记录的字段、变量或awk的表达式:
(3)如省略item,相当于print $0
2、 变量
2.1 内建变量
FS: 输入字段分隔符, 默认为空白字符
OFS: 输出字段分隔符, 默认为空白字符
RS: 输入时的换行符
ORS: 输出时的换行符
NF: 字段数量
{print NF} {print $NF}
NR: 行数
FNR: 各文件分别计数: 行数:
FILENAME: 当前文件名:
ARGC: 命令行参数的个数:
ARGV: 数组,保存的是命令行所给定的各参数:
2.2 自定义变量
(1)-v var=value
变量名区分字符大小写:
(2)在program中直接定义
3、printf命令
格式化输出:printf FORMAT, item1, item2, ...
(1)FORMAT必须给出;
(2)不会自动换行,需要显示给出换行控制符, \n
(3)FORMAT 中需要分别为后面的每一个item指定一个格式化符号:
格式符:
%c 显示字符的ASCII码
%d %i 显示十进制整数
%e %E 科学计数法数值显示
%f 显示为浮点数
%g %G 以科学计数法或浮点形式显示数值
%s 显示字符串
%u 无符号整数
%% 显示%自身
修饰符:
#[.#] 第一个数字控制显示的宽度: 第二个#表示小数点后的精度:
%3.1f
- 左对齐
+ 显示数值的符号
4、操作符
算术操作符:
x+y, x-y, x*y, x/y, X^y, x%y
-x
+x: 转换为数值:
字符串操作符: 没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=,*=, /=, %=, ^=
++, --
比较操作符:
>, >=, <, <=, !=, ==
模式匹配符:
~ 左边是否匹配右边
!~ 左边是否不匹配右边
逻辑操作符:
&&
||
!
函数调用:
function_name(argu1, argu2, ...)
条件表达式:
selector?if-true-expression:if-false-expression
[root@centos7 ~]#awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%s\n",$1,usertype}' /etc/passwd root:Sysadmin or SysUser bin:Sysadmin or SysUser daemon:Sysadmin or SysUser adm:Sysadmin or SysUser lp:Sysadmin or SysUser sync:Sysadmin or SysUser shutdown:Sysadmin or SysUser halt:Sysadmin or SysUser mail:Sysadmin or SysUser operator:Sysadmin or SysUser games:Sysadmin or SysUser ftp:Sysadmin or SysUser nobody:Sysadmin or SysUser pegasus:Sysadmin or SysUser systemd-network:Sysadmin or SysUser
5、PATTERN
(1)empty: 空模式,匹配每一行:
(2)/regular expression/: 仅处理能够被此处的模式匹配到的行:
[root@centos7 ~]#awk '/^UUID/{print $1}' /etc/fstab
UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f
UUID=6e6694fc-5a2f-47a1-b96b-509621e5fc1e
UUID=1828df2b-47f3-442d-9681-ca17539861d9
UUID=111bb92e-4d79-486a-afaf-38ba79856d30
[root@centos7 ~]#awk '!/^UUID/{print $1}' /etc/fstab // !表示取反
#
#
(3)relation expression: 关系表达式: 结果有真有假:结果为真才会被处理:
真:结果为非0值,非空字符串:
[root@centos7 ~]#awk -F: '$3>=1000{print $1,$3}' /etc/passwd
nfsnobody 65534
xp018970 1000
[root@centos7 ~]#awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd
root /bin/bash
xp018970 /bin/bash
(4)line range: 行范围
startline,endline: /pattern1/,/pattern2/
[root@centos7 ~]#awk -F: '(NR>=3&&NR<=10){print $1}' /etc/passwd
daemon
adm
lp
sync
shutdown
halt
mail
operator
(5)BEGIN/END模式
BEGIN{}: 仅在开始(处理文件中的文本)之前执行一次:
END{}:仅在文本处理完成之后执行一次:
[root@centos7 ~]#awk -F: 'BEGIN{print "Username Uid \n============================"}{printf "%-19s|%d\n", $1,$3}END{print "============================ \n END "}' /etc/passwd
Username 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
nobody |99
pegasus |66
systemd-network |192
dbus |81
polkitd |999
unbound |998
libstoragemgmt |997
rpc |32
colord |996
saslauth |995
abrt |173
setroubleshoot |994
rtkit |172
pulse |171
rpcuser |29
nfsnobody |65534
named |25
radvd |75
qemu |107
chrony |993
mysql |27
tss |59
geoclue |992
hacluster |189
usbmuxd |113
cockpit-ws |991
gluster |990
gdm |42
gnome-initial-setup|989
sshd |74
avahi |70
postfix |89
ntp |38
tcpdump |72
xp018970 |1000
dovecot |97
dovenull |988
============================
END
6、 控制语句
if(condition){statements}
if(condition){stations} else {statements}
while(condition){stations}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array
exit
{ statements }
6.1 if-else
语法:if(condition){stations} else {statements}
[root@centos7 ~]#awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd
nfsnobody 65534
xp018970 1000
[root@centos7 ~]#awk -F: '{if($3>=1000) {printf "%19s : Common User\n",$1} else {printf "%19s : root or Sysuser\n", $1} }' /etc/passwd
root : root or Sysuser
bin : root or Sysuser
daemon : root or Sysuser
adm : root or Sysuser
lp : root or Sysuser
sync : root or Sysuser
shutdown : root or Sysuser
[root@centos7 ~]#awk -F: '{if($NF=="/bin/bash") printf "%8s:%s \n", $1,$NF}' /etc/passwd
root:/bin/bash
xp018970:/bin/bash
[root@centos7 ~]#awk '{if(NF>5) print $0}' /etc/fstab //默认为空白字符为分隔符,字段数大于5,就打印整行
[root@centos7 ~]#df -h |awk -F '[[:space:]]+|%' '/^\/dev/ {print $1,$5}' |awk '{if($2>=80) printf "WarningDisk : %s\n", $1}'
WarningDisk : /dev/sr0
[root@centos7 ~]#df -h |awk -F '[[:space:]]+|%' '$0 ~ "^/dev" {print $1,$5}' |awk '$2>=80{print $1}'
/dev/sr0
[root@centos7 ~]#df -h |awk -F"%" '/^\/dev/{print $1}' | awk '{if($NF>=30) printf "warning disk:%s\n", $1}'
warning disk:/dev/sda3
warning disk:/dev/sr0
使用场景:对awk取得的整数行或某个字段做条件判断:
6.2 while 循环
语法:while(condition)statement
条件“真”,进入循环: 条件“假”,退出循环:
使用场景:对一行内的多个字段逐一类似处理时使用:对数组中的各元素逐一处理时使用:
[root@centos7 ~]#awk '/^[[:space:]]*linux16/ {i=1;while(i<NF) {print $i,length($i);i++ }}' /etc/grub2.cfg
linux16 7
/vmlinuz-4.20.3-1.0-xinzhoulinux 32
root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
[root@centos7 ~]#awk '/^[[:space:]]*linux16/ {i=1;while(i<NF) {if(length($i)>=7) {print $i,length($i)};i++ }}' /etc/grub2.cfg
linux16 7
/vmlinuz-4.20.3-1.0-xinzhoulinux 32
root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
crashkernel=auto 16
linux16 7
/vmlinuz-3.10.0-862.el7.x86_64 30
root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
crashkernel=auto 16
linux16 7
/vmlinuz-0-rescue-18ed42c1c89e4d28870e69320e88d637 50
root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
crashkernel=auto 16
6.3 do-while 循环
语法:do statement while (condition)
意义:至少执行一次循环体
6.4 for循环
语法:for(expr1;expre2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
[root@centos7 ~]#awk '/^[[:space:]]*linux16/ {for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
linux16 7
/vmlinuz-4.20.3-1.0-xinzhoulinux 32
root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=en_US.UTF-8 16
linux16 7
特殊用法:
能够遍历数组中的元素:
语法:for(var in array) {for-body}
7、array
关联数组:array[index-expression]
index-expression:
(1)可使用任何字符串:字符串要使用双引号:
(2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”:
若要判断数组中是否存在某元素,要使用“index in array”格式进行:
weekdays["mon"]="Monday"
[root@centos7 ~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
Monday
[root@centos7 ~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
Tuesday
[root@centos7 ~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
Tuesday
Monday
注意:var会遍历array中的每个索引:
[root@centos7 ~]#tail -4 /etc/fstab |awk '{print "hello: " $1,$2}' hello: UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f / hello: UUID=6e6694fc-5a2f-47a1-b96b-509621e5fc1e /boot hello: UUID=1828df2b-47f3-442d-9681-ca17539861d9 /data hello: UUID=111bb92e-4d79-486a-afaf-38ba79856d30 swap
[root@centos7 ~]#awk -v FS=':' '{print $1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail operator games ftp nobody pegasus
[root@centos7 ~]#awk -v FS=':' -v OFS='=====' '{print $1,$3,$7}' /etc/passwd //FS: 输入字段分隔符, 默认为空白字符 OFS: 输出字段分隔符, 默认为空白字符 root=====0=====/bin/bash bin=====1=====/sbin/nologin daemon=====2=====/sbin/nologin adm=====3=====/sbin/nologin lp=====4=====/sbin/nologin sync=====5=====/bin/sync shutdown=====6=====/sbin/shutdown halt=====7=====/sbin/halt mail=====8=====/sbin/nologin operator=====11=====/sbin/nologin games=====12=====/sbin/nologin
[root@centos7 ~]#awk -v RS=' ' '{print}' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin pegasus:x:66:65:tog-pegasus OpenPegasus
[root@centos7 ~]#awk -v RS=' ' -v ORS='###' '{print}' /etc/passwd // RS: 输入时的换行符 ORS: 输出时的换行符 root:x:0:0:root:/root:/bin/bash games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP###User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin pegasus:x:66:65:tog-pegasus###OpenPegasus###WBEM/CIM###services:/var/lib/Pegasus:/sbin/nologin systemd-network:x:192:192:systemd###Network###Management:/:/sbin/nologin
[root@centos7 ~]#awk '{print NF}' /etc/fstab //NF: 字段数量 01 2 10 1 9 12 1 6 6 6 6
[root@centos7 ~]#awk '{print NR}' /etc/fstab //NR: 行数 1 2 3 4 5 6 7 8 9 10
[root@centos7 ~]#awk '{print FNR}' /etc/fstab /etc/issue //FNR: 各文件分别计数: 行数: 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3
[root@centos7 ~]#awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue //ARGC: 命令行参数的个数: 3
[root@centos7 ~]#awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/issue //ARGV: 数组,保存的是命令行所给定的各参数: awk [root@centos7 ~]#awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/issue //ARGV: 数组,保存的是命令行所给定的各参数: /etc/fstab [root@centos7 ~]#awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue //ARGV: 数组,保存的是命令行所给定的各参数: /etc/issue
[root@centos7 ~]#awk -v test="hello world" 'BEGIN{print test}' hello world [root@centos7 ~]#awk 'BEGIN{test="hello world";print test}' hello world
[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 Username: shutdown Uid: 6 Username: halt Uid: 7 Username: mail Uid: 8 Username: operator Uid: 11
[root@centos7 ~]#awk -F: '{printf "Username: %19s 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 Username: shutdown Uid: 6 Username: halt Uid: 7 Username: mail Uid: 8 Username: operator Uid: 11 Username: games Uid: 12 Username: ftp Uid: 14 Username: nobody Uid: 99 Username: pegasus Uid: 66 Username: systemd-network Uid: 192
[root@centos7 ~]#awk -F: '{printf "Username: %-19s Uid: %d\n", $1,$3}' /etc/passwd // 19字符串的宽度, 加- 左对齐显示 Username: root Uid: 0 Username: bin Uid: 1 Username: daemon Uid: 2 Username: adm Uid: 3 Username: lp Uid: 4 Username: sync Uid: 5 Username: shutdown Uid: 6 Username: halt Uid: 7 Username: mail Uid: 8 Username: operator Uid: 11 Username: games Uid: 12 Username: ftp Uid: 14 Username: nobody Uid: 99 Username: pegasus Uid: 66