一、简介
awk命令是一种编程语言,用于在linux/unix下对文本和数据进行扫描和处理的工具,其数据来源可以为标准输入、文件、管道等等。awk命令会从第一行输入开始逐行扫描至最后一行,寻找其中匹配特定模式的行,并在相应的行上执行用户指定的操作。Awk命令的基本架构由模式匹配和处理动作组成,默认处理动作为print打印行。
二、awk命令的使用
1、命令格式
gawk [options] 'program...' FILE ...
2、常见选项
-F fs:指明字段分隔符;
-v var=value:自定义变量;
-f programfile:从文件中读取program命令;
3、program语句
其program语句的常见格式为:PATTERN{action,statements}
,其中多个program语句之间通过;
分隔。
- 其中PATTERN格式为:
1)empty:空模式,表示匹配每一行,如:awk -F: '{print $1,$3}' /etc/passwd 表示以:
为分隔符,打印每行的第一和第三个字段 。
2)/regular expression/:仅处理能够被此模式匹配到的行,如:awk -F: '/^root/{print $1,$3}' /etc/passwd,表示以:
为分隔符,打印以root开头的行的第一和第三个字段;
3)/PATTERN1/,/PATTERN2/:表示仅处理从第一个被pattern1匹配到行,到第一个被pattern2所匹配的行之间的所有行,如:awk -F: '/root/,/shutdown/{print $1,$3}' /etc/passwd,表示以:
为分隔符,打印从第一个以root开头的行到第一个以shutdown开头的行之间的所有行的第一和第三个字段。
4)relation expression:使用关系表达式进行匹配,只有结果会真的行才会被处理,如:awk -F: '(NR>=10&&NR<=20){print $1,$3}' /etc/passwd,表示以:
为分隔符,打印10-20行的第一和第三个字段;
5)BEGIN{}和END{}:
BEGIN{}:表示在开始处理行前执行一次指定的操作;
END{}:表示在结束对行的处理后执行一次指定的操作;
如:awk -F: 'BEGIN{print "This is the begin."};{print $1,$3};END{print "This is the end."}' /etc/passwd,表示在执行行打印操作前,先打印指定的字符串"This is the begin.",在执行行打印操作后再打印字符串“This is the end.”
- program语句的变量
program中内置了一些变量,在编写program语句时能够直接调用相应的变量,进而简化语句。调用内建变量时无需加$
。
FS:输入字段分隔符,默认为空白字符;
OFS:输出字段分隔符,默认为空白字符;
RS:输入时的换行符;
ORS:输出时的换行符;
NF:每行的字段数,$NF表示最后一个字段;
NR:表示行数;
FNR:若提供多个文件,则分别计算各文件的行数;
FILENAME:当前文件名;
ARGC:命令行参数的个数;
ARGV:参数数组,保存的是命令行给定的各参数;
另外也可以在awk命令中自定义相关的变量,可以使用-v选项自定义变量,也可以在语句当中进行赋值操作,如:awk 'BEGIN{test="hello awk"; print test}'、ls -l | awk '/root/{hello="this is a test.";print $3,hello}'
- action
常见的action动作有:print、printf
1)print命令
其使用格式类似于print item1,item2,...
,使用逗号作为分隔符,输出的item可以为字符串,也可以为数值,也可以为当前记录的字段、变量或表达式等。如果省略了item,则相当于print $0打印所有行。
2)printf命令
printf命令常用于格式化输出awk命令的执行结果信息。其格式类似于printf FORMAT,item1,item2...
,其中必须指定FORMAT格式;如需换行,需手动添加\n换行符;在FORMAT中需要分别为后面的每个item指定一个格式符。
其对应的格式符有:
%c: 显示字符的ASCII码;
%d, %i: 显示十进制整数;
%e, %E: 科学计数法数值显示;
%f:显示为浮点数;
%g, %G:以科学计数法或浮点形式显示数值;
%s:显示字符串;
%u:无符号整数;
%%: 显示%自身
其中还可以使用以下修饰符对格式符进行输出格式的整理:
#[.#]:第一个#数字控制格式符显示的宽度;第二个#数字表示格式符显示的内容的精确度,只显示最大长度为#的格式符内容;
-:左对齐,默认为右对齐;
+:显示数值的符号;
如下示例:
[root@localhost ~]# awk -F: '{printf "The user:%-20s User ID:%15d\n",$1,$3} ' /etc/passwd
The user:root User ID: 0
The user:bin User ID: 1
The user:daemon User ID: 2
The user:adm User ID: 3
The user:lp User ID: 4
The user:sync User ID: 5
The user:shutdown User ID: 6
The user:halt User ID: 7
The user:mail User ID: 8
The user:operator User ID: 11
The user:games User ID: 12
The user:ftp User ID: 14
The user:nobody User ID: 99
The user:avahi-autoipd User ID: 170
The user:systemd-bus-proxy User ID: 999
The user:systemd-network User ID: 998
The user:dbus User ID: 81
The user:polkitd User ID: 997
The user:tss User ID: 59
The user:postfix User ID: 89
The user:sshd User ID: 74
-
条件表达式
awk命令的program语句也支持通过条件表达式来判断控制,其表达式支持常见的算术、赋值、比较等操作符,如:+,-,*,/,%,=,+=,>,<,~等等的操作符,也支持逻辑操作与或非,其格式为:
awk [optioins] '{selector?if-true-expression:if-false-expression;action statements}' /PATH/TO/SOMEFILE
如根据用户ID判断对应用户是系统用户还是普通用户:
[root@localhost ~]# awk -F: '{$3>=1000?usertype="this is a common user.":usertype="This is a system user.";printf "%20s:%-s\n",$1,usertype}' /etc/passwd
root:This is a system user.
bin:This is a system user.
daemon:This is a system user.
adm:This is a system user.
lp:This is a system user.
sync:This is a system user.
shutdown:This is a system user.
halt:This is a system user.
mail:This is a system user.
operator:This is a system user.
games:This is a system user.
ftp:This is a system user.
nobody:This is a system user.
pegasus:This is a system user.
avahi-autoipd:This is a system user.
ods:This is a system user.
systemd-bus-proxy:This is a system user.
systemd-network:This is a system user.
dbus:This is a system user.
polkitd:This is a system user.
sssd:This is a system user.
apache:This is a system user.
三、使用案例
- 格式化打印当前系统的用户列表
[root@localhost ~]# awk -F: 'BEGIN{print "User lists"};{printf "User:%-25s\n",$1};END{print "This is the end."}' /etc/passwd
User lists
User:root
User:bin
.....
User:nologin
User:hadoop
This is the end.
[root@localhost ~]#
- 搜索打印以/bin/bash为默认shell的用户信息:
[root@localhost ~]# awk -F: '$7~/.*bash\>/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
amandabackup:x:33:6:Amanda user:/var/lib/amanda:/bin/bash
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
centos:x:1001:1001::/home/centos:/bin/bash
federo:x:1002:1002::/home/federo:/bin/bash
counter:x:1003:1004::/home/counter:/bin/bash
charlie:x:1004:1005::/home/charlie:/bin/bash
Jone:x:1006:1007::/Jone:/bin/bash
Williom:x:1200:1005::/home/Williom:/bin/bash
mageia:x:1100:1100::/home/linux:/bin/bash
bash:x:2003:2003::/home/bash:/bin/bash
testbash:x:2004:2004::/home/testbash:/bin/bash
basher:x:2005:2005::/home/basher:/bin/bash
hadoop:x:2007:2007::/home/hadoop:/bin/bash
- 获取系统网卡的Ip地址
[root@localhost ~]# ifconfig | awk '/inet\>/{print $2}'
188.88.88.42
127.0.0.1
192.168.122.1
- 对比两个文件的内容
[root@localhost tmp]# cat a.sh
hello,world
i am charlie
this is my linux
magedeu
[root@localhost tmp]# cat b.sh
1
hello,world
2
i am charlie
3
this is my linux
4
magedeu
[root@localhost tmp]# awk 'FNR==NR{a[$0];next}{if($0 in a)print $0}' a.sh b.sh
hello,world
i am charlie
this is my linux
magedeu
上述awk命令在FNR和NR的等式成立的时候,将文件a.sh每行的内容作为数组a下标,然后执行next跳过后续if判断语句;当FNR和NR的等式不成立的时候,不执行a[$0];next,执行后面的if语句,判断b.sh中的每行内容是否为a数组中的元素下标,是的话就打印该行信息。
同理,利用取反找出不同的行:
[root@localhost tmp]# awk 'FNR==NR{a[$0];next}{if (!($0 in a))print $0}' a.sh b.sh
1
2
3
4
- 从文件中读取program语句执行awk命令
这里以上面文件对比的命令为例:
[root@localhost tmp]# cat awk.sh
FNR==NR{
a[$0];
next
}
{
if (!($0 in a))
print $0
}
[root@localhost tmp]# awk -f awk.sh a.sh b.sh
1
2
3
4
如有错误,欢迎指点~