文章目录
- 九、shell编程之awk
- 9.1 什么是awk
- 9.2 awk的工作流程
- 9.3 awk程序执行方式
- 9.4 awk基本语法
- 9.4.1 awk的输出
- 9.4.2 awk的变量
- 9.4.3 awk操作符
- 9.4.4 awk的模式
- 9.4.5 awk控制语句
- 9.4.6 awk使用数组
- 9.4.7 awk内置函数
- 9.5 awk 案例
- 9.5.2 网站日志分析
九、shell编程之awk
9.1 什么是awk
awk是Linux以及UNIX环境中现有的功能最强大的数据处理工具。简单地讲,awk是一种处理文本数据的编程语言。awk的设计使得它非常适合于处理由行和列组成的文本数据。而在Linux或者UNIX环境中,这种类型的数据是非常普遍的。
除此之外,awk 还是一种编程语言环境,它提供了正则表达式的匹配,流程控制,运算符,表达式,变量以及函数等一系列的程序设计语言所具备的特性。它从C语言中获取了一些优秀的思想。awk程序可以读取文本文件,对数据进行排序,对其中的数值执行计算以及生成报表等。
9.2 awk的工作流程
awk命令的基本语法如下:
awk 'pattern { actions }'
在上面的语法中,pattern表示匹配模式,actions表示要执行的操作。以上语法表示,当某个文本行符合pattern指定的匹配规则时,执行actions所执行的操作。在上面的语法中,pattern和actions都是可选的,但是两者必须保证至少有一个。如果省略匹配模式pattern,则表示对所有的文本行执行actions所表示的操作;如果省略actions,则表示将匹配成功的行输出到屏幕。
对于初学者来说,搞清楚awk的工作流程非常重要。只有在掌握了awk的工作流程之后,才有可能用好awk来处理数据。在awk处理数据时,它会反复执行以下4个步骤:
• (1)自动从指定的数据文件中读取行文本。
• (2)自动更新awk的内置系统变量的值,例如列数变量NF、行数变量NR、行变量$0以及各个列变量
• $1、$2等等。
• (3)依次执行程序中所有的匹配模式及其操作。
• (4)当执行完程序中所有的匹配模式及其操作之后,如果数据文件中仍然还有未读取的数据行,则返回
• 到第(1)步,重复执行(1)~(4)的操作。
9.3 awk程序执行方式
1.通过命令行执行awk程序,语法如下:
awk 'program-text' datafile
2.执行awk脚本
在awk程序语句比较多的情况下,用户可以将所有的语句写在一个脚本文件中,然后通过awk命令来解释并执行其中的语句。awk调用脚本的语法如下:
awk -f program-file file ..
在上面的语法中,-f选项表示从脚本文件中读取awk程序语句,program-file表示awk脚本文件名称,file表示要处理的数据文件。
3.可执行脚本文件
在上面介绍的两种方式中,用户都需要输入awk命令才能执行程序。除此之外,用户还可以通过类似于Shell脚本的方式来执行awk程序。在这种方式中,需要在awk程序中指定命令解释器,并且赋予脚本文件的可执行权限。其中指定命令解释器的语法如下:
#!/bin/awk -f
以上语句必须位于脚本文件的第一行。然后用户就可以通过以下命令执行awk程序:
awk-script file
其中,awk-script为awk脚本文件名称,file为要处理的文本数据文件。
9.4 awk基本语法
awk [options] 'script' file1 file2, ...
awk [options] 'PATTERN { action }' file1 file2, ...
9.4.1 awk的输出
(1)print的使用格式:
print item1,item2,…
要点:
- 各项目之间使用逗号隔开,而输出时则以空白字符分隔;
- 输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
- print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print “”;
示例:
[root@localhost ~]# awk 'BEGIN { print "line one\nline two\nline three"}'
line one
line two
line three
[root@localhost ~]# awk 'BEGIN{print "This","is","test"}'
This is test
[root@localhost ~]# awk -F: '{print $1,$3}' /etc/passwd | head -n 3
root 0
bin 1
daemon 2
(2)printf命令的使用格式:
虽然大多数情况下awk的print语句可以完成任务,但有时我们还需要对格式做更多的控制。awk提供了printf函数来实现字符串的格式化。这个函数的功能和语法与C语言中的printf()函数基本相同,如下:
printf(format, [arguments])
其中圆括号是可选的,第1个参数format是一个用来描述输出格式的字符串,通常以引号括起来的字符串常量
的形式提供。arguments为一个参数列表,表示用来显示的数据,可以是变量名等,多个参数之间用逗号隔开。参数列表的项是有顺序的,与前面的格式化字符串中的格式说明相对应。printf语句不会自动打印换行符。
1、其与print命令的最大不同是,printf需要指定format;
2、format用于指定后面的每个item的输出格式;
3、printf语句不会自动打印换行符;\n
format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码;
%d, %i:十进制整数;
%e, %E:科学计数法显示数值;
%f: 显示浮点数;
%g, %G: 以科学计数法的格式或浮点数的格式显示数值;
%s: 显示字符串;
%u: 无符号整数;
%%: 显示%自身;
修饰符:
N: 显示宽度;
-: 左对齐;
+:显示数值符号;
示例:
[root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd |head
-n 3
root 0
bin 1
daemon 2
(3)输出重定向
print items > output-file
print items >> output-file
print items | command
示例:
[root@localhost ~]# awk -F: '{printf "%-15s %i\n",$1,$3 > "test1" }' /etc/passwd
9.4.2 awk的变量
与其他的程序设计语言一样,awk本身支持变量的相关操作,包括变量的定义和引用,以及参与相关的运算等。此外,还包含了许多内置的系统变量。
变量的作用是用来存储数据。变量由变量名和值两部分组成,其中变量名是用来实现变量值的引用的途径,而变量值则是内存空间中存储的用户数据。
awk的变量名只能包括字母、数字和下划线,并且不能以数字开头。例如abc、a、z以及a123都是合法的变量名,而123abc则是非法的变量名。另外,awk的变量名是区分大小写的,因此,X和x分别表示不同的变量。
在awk中定义变量的方法非常简单,只要给出一个变量名并且赋予适当的值即可。awk中的变量类型分为两种,分别为字符串和数值。但是在定义awk变量时,毋需指定变量类型,awk会根据变量所处的环境自动判断。如果没有指定值,数值类型的变量的缺省值为0,字符串类型的变量的缺省值为空串。awk提供了许多非常实用的系统变量,例如字段变量、字段数变量以及记录数变量等。
(1)awk内置变量
示例:
[root@localhost ~]# echo "this is" > test.txt
[root@localhost ~]# awk 'BEGIN {OFS="#"} {print $1,$2,"a","test"}' test.txt
this#is#a#test
[root@localhost ~]# awk 'BEGIN{print ENVIRON["PATH"]}'
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
(2) 用户自定义变量
awk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。awk变量名称区分字符大小写。
• 1、在awk中给变量赋值使用赋值语句进行
示例:
[root@localhost ~]# awk 'BEGIN{test="hello";print test}'
hello
2、在命令行中使用赋值变量
awk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:
[root@localhost ~]# awk -v test="hello" 'BEGIN {print test}'
hello
9.4.3 awk操作符
awk是一种编程语言环境,因此,它也支持常用的运算符以及表达式,例如算术运算、逻辑运算以及关系运算等。
(1)awk支持常用的算术运算,这一点与其他的程序设计语言基本相同。
示例:
[root@localhost ~]# awk 'BEGIN{x=2;y=3;print x**y,x^y,x*y,x/y,x+y,x-y,x%y}'
8 8 6 0.666667 5 -1 2
(2)赋值运算符
(3)条件运算符
awk中的条件运算符只有一个,其语法如下:
expression?value1:value2
这是一个三目运算符,当表达式expression的值为真时,返回值为value1;否则,返回值为value2。
示例:
bash
[root@localhost ~]# cat file
3 6
10 9
3 3
[root@localhost ~]# awk '{max=$1>$2?$1:$2;print NR,"max=",max}' file
1 max= 6
2 max= 10
3 max= 3
(4)逻辑运算符
awk支持3种逻辑运算,分别为逻辑与、逻辑或和逻辑非
awk支持3种逻辑运算,分别为逻辑与、逻辑或和逻辑非
5)关系运算符
[root@localhost test11]# awk '$1~/^w/ {print}' file
wangmei 70
[root@localhost ~]# awk -F: 'BEGIN {printf "%-10s %-5s
%-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-10s %-5s %-15s\n",$1,$3,$7}' /etc/passwd
user uid shell
root 0 /bin/bash
bin 1 /sbin/nologin
[root@localhost ~]# awk -F: 'BEGIN {printf "%-10s %-5s
%-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-10s %-5s
%-15s\n",$1,$3,$7} END{print "-------end---------"}' /etc/passwd
user uid shell
root 0 /bin/bash
bin 1 /sbin/nologin
-------end---------
说明:$3==0,$7~"nologin"表示匹配符合条件1到条件2之间的所有行(成对多次匹配),如果条件2不成立,则一直匹配到文件尾部
[root@localhost ~]# cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t" $3}'查阅/etc/passwd文件第三列小于10以下的数据,并且仅列出账号与第三列。但是这样的写法会导致第一行无法正确显示出来,由于读入第一行的时候,变量$1,$2……默认还是以空格符为分隔的,定义的FS=“:”仅能在第二行后才开始生效。可以使用BEGIN这个关键字来达到从第一行读入。
[root@localhost ~]# cat /etc/passwd | awk 'BEGIN {FS=":"} $3 < 10 {print $1 "\t" $3}'
[root@localhost ~]# cat /etc/passwd | awk -F : '$3 < 10 {print $1 "\t" $3}'
说明:$3变量是空值,但是后面与之作比较的是整数,所以$3的值是0,满足条件,所以打印$1的结果,在此打印$3的结果时$3是空串。
(6)其他运算符
awk还支持其他的一些运算符,例如正号+、负号-、自增++以及自减–等,这些运算符的使用方法与其他的语言的使用方法完全相同。
9.4.4 awk的模式
awk的基本语法:
awk [options] 'PATTERN { action }' file1 file2, ...
在awk中,匹配模式处于非常重要的地位,它决定着匹配模式后面的操作会影响到哪些文本行。awk中的匹配模式主要包括关系表达式、正则表达式、混合模式,BEGIN模式以及END模式等。
(1)关系表达式
awk提供了许多关系运算符,例如大于>、小于<或者等于==等。awk允许用户使用关系表达式作为匹配模式,当某个文本行满足关系表达式时,将会执行相应的操作。
[root@localhost test11]# cat file
liming 80
wangmei 70
zhangsan 90
lisi 81
[root@localhost test11]# awk '$2 > 80 {print}' file
zhangsan 90
lisi 81
(2)正则表达式
awk支持以正则表达式作为匹配模式,与sed一样,用户需要将正则表达式放在两条斜线之间,其基本语法如下:
/regular_expression/
[root@localhost test11]# awk '/^l/{print}' file
liming 80
lisi 81
[root@localhost test11]# awk '/^l|z/{print}' file
liming 80
zhangsan 90
lisi 81
(3)混合模式
awk不仅支持单个的关系表达式或者正则表达式作为模式,还支持使用逻辑运算符&&、||或者!将多个表达式组合起来作为一个模式。其中,&&表示逻辑与,||表示逻辑或,!表示逻辑非。
[root@localhost test11]# awk '/^l/ && $2>80 {print}' file
lisi 81
(4)区间模式
awk还支持一种区间模式,也就是说通过模式可以匹配一段连续的文本行。区间模式的语法如下:
pattern1, pattern2
其中,pattern1和pattern2都是前面所讲的匹配模式,可以是关系表达式,也可以是正则表达式等。当然,也可以是这些模式的混合形式。
[root@localhost test11]# awk '/^liming/,$2==90 {print}' file
liming 80
wangmei 70
zhangsan 90
(5)BEGIN模式
BEGIN模式是一种特殊的内置模式,其成立的时机为awk程序刚开始执行,但是又尚未读取任何数据之前。因此,该模式所对应的操作仅仅被执行一次,当awk读取数据之后,BEGIN模式便不再成立。所以,用户可以将与数据文件无关,而且在整个程序的生命周期中,只需执行1次的代码放在BEGIN模式对应的操作中。
[root@localhost test11]# cat 1.sh
#!/bin/awk -f
BEGIN {print "hello,world"}
[root@localhost test11]# ./1.sh
hello,world
[root@localhost ~]# awk -F: 'BEGIN {printf "%-15s %-3s
%-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-15s %-3s
%-15s\n",$1,$3,$7}' /etc/passwd
(6)END模式
END模式是awk的另外一种特殊模式,该模式成立的时机与BEGIN模式恰好相反,它是在awk命令处理完所有的数据,即将退出程序时成立,在此之前,END模式并不成立。无论数据文件中包含多少行数据,在整个程序的生命周期中,该模式所对应的操作只被执行1次。因此,一般情况下,用户可以将许多善后工作放在END模式对应的操作中。
[root@localhost test11]# cat 2.sh
#! /bin/awk -f
BEGIN {
print "scores report"
print "================================="
}
{ print }
END {
print "================================"
print "printing is over"
}
[root@localhost test11]# ./2.sh file
scores report
=================================
liming 80
wangmei 70
zhangsan 90
lisi 81
================================
printing is over
[root@localhost ~]# awk -F: 'BEGIN {printf "%-15s %-3s
%-15s\n","user","uid","shell"} $3==0,$7~"nologin" {printf "%-15s %-3s
%-15s\n",$1,$3,$7} END {print "-----End file-----"}' /etc/passwd
9.4.5 awk控制语句
作为一种程序设计语言,awk支持程序的流程控制,例如条件判断、循环以及其他的一些流程控制语句,例如continue、break以及exit等。掌握这些基本的流程控制语句,对于编写出结构良好的程序非常重要。
(1)if语句的功能是根据用户指定的条件来决定执行程序的哪个分支,其语法如下:
if (expression)
{
statement1
statement2
}
else
{
statement3
statement4
}
[root@localhost test11]# cat 3.sh
#! /bin/awk -f
{
if ($2 >= 90) {
print $1,"A"
}
else
{
if($2 >= 80 && $2 < 90)
{
print $1,"B"
}
else
{
print $1,"C"
}
}
}
[root@localhost test11]# cat file
liming 80
wangmei 70
zhangsan 90
lisi 81
[root@localhost test11]# ./3.sh file
liming B
wangmei C
zhangsan A
lisi B
[root@localhost ~]# awk -F: '{if ($1=="root") printf "%-10s %-15s\n", $1,
"Admin"; else printf "%-10s %-15s\n",$1, "Common User"}' /etc/passwd | head -n 3
[root@localhost ~]# awk '{if ($1>$2) print NR,"max =",$1;else print NR,"max
=",$2}' file ...
(2)while语句是另外一种常用的循环结构,其语法如下:
while (expression)
{
statement1
statement2
……
}
当表达式expression的值为真时,执行循环体中的statement1以及statement2等语句。如果循环体中只包含一条语句,则可以省略大括号。
[root@localhost ~]# awk 'BEGIN{while(i<=100) {sum+=i;i++}print "sum=",sum}'
sum= 5050
[root@localhost test11]# cat 4.sh
#! /bin/awk -f
BEGIN {
i=0
while (++i <= 9)
{
print i^2
}
}
[root@localhost test11]# ./4.sh
1
4
9
16
25
36
49
64
81
(3)awk还支持另外一种while循环语句,其语法如下:
do {
statement1
statement2
...
}while (expression)
同样,当表达式expression的值为真时执行循环体中的语句。
[root@localhost test11]# cat 5.sh
#! /bin/awk -f
BEGIN {
i=1
do
{
print i^2
}while (++i<=9)
}
[root@localhost test11]# ./5.sh
1
4
9
16
25
36
49
64
81
(4)for语句
for循环语句通常用在循环次数已知的场合中,其语法如下:
for(expression1; expression2; expression3)
{
statement1
statement2
...
}
在上面的语法中,表达式expression1通常用来初始化循环变量,表达式expression2通常用来指定循环执行的条件,表达式expression3通常用来改变循环变量的值。当表达式expression2的值为真时,执行循环体中的语句。
[root@localhost ~]# awk 'BEGIN {for(i=1;i<=100;i++){sum+=i;}print "sum=",sum}'
sum= 5050
[root@localhost test11]# cat 6.sh
#! /bin/awk -f
BEGIN {
for(i=1;i<=9;i++)
{
for(j=1;j<=i;j++)
{
if(i*j<10)
{
row=row" "i*j
}
else
{
row=row" "i*j
}
}
print row
row=""
}
}
[root@localhost test11]# ./6.sh
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72 81
for循环还可以用来遍历数组元素:
语法: for(变量 in 数组){语句}
#统计用户的shell
[
root@localhost ~]# awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd
(5)break语句
用户可以通过使用break语句在适当的时机退出for以及while等循环结构,而不必等到循环结构自己退出。
(6)continue语句
continue语句的主要功能是跳过循环结构中该语句后面的尚未执行的语句。break语句与continue语句的功能有着明显的区别,前者是直接退出循环结构,而后者是跳过循环体中尚未执行的语句,重新执行下一次循环。
(7)next语句
next语句的功能与continue语句非常相似,但是next语句并不是用在循环结构中,而是用在整个awk程序中。当awk执行程序时,如果遇到next语句,则提前结束对本行文本的处理,awk会继续读取下一行数据,并且从第一个模式及其操作开始执行。
例如,下面的命令将显示其ID号为奇数的用户:
[root@localhost ~]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd |head -n 3
bin 1
adm 3
sync 5
(8)exit语句
exit语句的功能是终止awk程序的执行。
9.4.6 awk使用数组
(1)读取数组array[index-expression]
index-expression可以使用任意字符串;需要注意的是,如果某数组元素事先不存在,那么在引用时,awk会自动创建此元素并初始化为空串;因此,要判断某数组中是否存在某元素,需要使用index in array的方式。
要遍历数组中的每一个元素,需要使用如下的特殊结构:
for (var in array) { statement1, … }
其中,var用于引用数组下标,而不是元素值;
示例:
[root@localhost ~]# netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print
a, S[a]}'
ESTABLISHED 1
LISTEN 10
每出现一次被/^tcp/模式匹配到的行,数组S[$NF]就加1,NF为当前匹配到的行的最后一个字段,此处用其值做为数组S的元素索引
;
(2)删除数组变量
从关系数组中删除数组索引需要使用delete命令。使用格式为:
delete array[index]
9.4.7 awk内置函数
(1)split(string, array [, fieldsep [, seps ] ])
功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;
[root@localhost ~]# date +%T | awk '{split($0,a,":");print a[1],a[2],a[3]}'
(2)length([string])
功能:返回string字符串中字符的个数;
[root@localhost ~]#awk 'BEGIN{print length("uplooking")}'
(3)substr(string, start [, length])
功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;
[root@localhost ~]#awk 'BEGIN{print substr("uplooking",u,2)}'
(4)system(command)
功能:执行系统command并将结果返回至awk命令
[root@localhost ~]# awk 'BEGIN{print system("whoami")}'
root
0 #系统命令执行之后的状态码
(5)systime()
功能:取系统当前时间
[root@localhost ~]# awk 'BEGIN{print systime()}'
(6)tolower(s)
功能:将s中的所有字母转为小写
[root@localhost ~]# awk 'BEGIN{print tolower("WWW.baidu.COM")}'
(7)toupper(s)
功能:将s中的所有字母转为大写
[root@localhost ~]# awk 'BEGIN{print toupper("WWW.baidu.COM")}'
9.5 awk 案例
9.5.1 系统连接状态
1) 查看TCP连接状态
[root@localhost ~]# netstat -nat |awk '/^tcp/ {print $NF}'| sort|uniq -c |sort - rn
netstat -nat | awk '/^tcp/ {++state[$NF]}; END {for(key in state) print state[key],key}'| sort -nr
2) 查找请求数20个IP(常用于查找攻击源)
[root@localhost ~]# netstat -nat|awk '/^tcp/ {print $5}'|awk -F: '{print $1}'|
sort | uniq -c |sort -nr | head -n 20
[root@localhost ~]# netstat -nat|awk '/^tcp/ {print $5}'|awk -F: '{++IP[$1]};END
{for (ip in IP) print IP[ip],ip}'|sort -nr | head -n 20
3)用tcpdump嗅探80端口的访问看看谁最高
[root@localhost ~]# tcpdump -i eno16777736 -tnn dst port 80 -c 1000 | awk -F"."
'{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -nr |head -20
9.5.2 网站日志分析
以apache为例
1)获取访问前10位的ip地址
[root@localhost ~]# awk '{a[$1] += 1;} END {for (i in a) printf("%d %s\n", a[i], i);}' 日志文件 | sort -n | tail
2)统计404的连接
[root@localhost ~]# awk '($(NF-1) ~/404/)' 日志文件 | awk '{print $(NF-1),$7}' | sort | head
9.5.3 AWK应用实战20例
• <1>输出当前系统所有用户的UID:
[root@localhost ~]# awk -F: '{print $3}' /etc/passwd
注释
:-F:指定分隔符为:$3指定第三段
• <2>输出当前系统所有用户的UID,在首行加入UserUid:
[root@localhost ~]# awk -F: 'BEGIN {print "Userid"}{print $3}' /etc/passwd
• <3>输出当前系统shell为/bin/bash的用户名,在最后一行加入END That is last line!!!
[root@localhost ~]# awk -F: '/bash$/{print $1}END{print "that is last line!!!"}' /etc/passwd
• <4>输出当前系统上GID为0的用户的用户名
[root@localhost ~]# awk -F : '$4==0{print $1}' /etc/passwd
root
• <5>输出当前系统上GID大于500的用户的用户名
[root@localhost ~]# awk -F : '$4>500{print $1}' /etc/passwd
• <6>输出当前系统上的所有用户名和UID,以“ # # ”为分隔符
[root@localhost ~]# awk -F : 'OFS="# #"{print $1,$3}' /etc/passwd
• <7>输出/etc/passwd文件中以“:”为分隔符的最后一段。
[root@localhost ~]# awk -F : '{print $NF}' /etc/passwd
• <8>对/etc/passwd文件中输出的每一行计数
[root@localhost ~]# awk '{print NR,$0}' /etc/passwd
• <9>对/etc/passwd、/etc/fstab文件中输出的每一行分别计数。
[root@localhost ~]# awk '{print FNR,$0}' /etc/passwd /etc/fstab
• <10>自定义变量
[root@localhost ~]# awk -v var="Linux.com.cn" 'BEGIN{print var}'
Linux.com.cn
[root@localhost ~]#awk 'BEGIN {var="linux.com.cn";print var}'
• <11>以printf格式输出用户名,UID、GID
[root@localhost ~]# awk -F: '{printf "%-15s %d %8i\n",$1,$3,$4}' /etc/passwd
• <12>检测当前系统上所有用户,如果用户名为root输出:Admin
如果用户名不为root输出:Common User
[root@localhost ~]# awk -F: '{if ($1=="root") printf "%-15s: %s\n", $1,"Admin"; else printf "%-15s: %s\n", $1, "Common User"}' /etc/passwd
• <13> 统计当前系统上UID大于500的用户的个数
[root@localhost ~]# awk -F: -v sum=0 '{if ($3>=500) sum++}END{print sum}' /etc/passwd
9
[root@localhost ~]# awk -F: '$3>500 {sum++} END {print sum}' /etc/passwd
• <14>读取/etc/passwd文件中的每一行的每一个字段,输出每个字段中字符个数大于等于四的字段。
[root@localhost ~]# awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
• <15>使用do-while语句输出/etc/passwd中每一行中的前三个字段
[root@localhost ~]# awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
• <16>使用for语句输出/etc/passwd中每一行中的前三个字段
[root@localhost ~]# awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
• <17>统计/etc/passwd文件中各种shell的个数
[root@localhost ~]# awk -F: '$NF!~/^$/{BASHsum[$NF]++}END{for(A in BASHsum) {printf "%-15s:%i\n",A,BASHsum[A]}}' /etc/passwd
注释:
$NF!~/^$/:最后一个字段非空
BASHsum[$NF]++:最后一个字段相同的加一
• <18> 显示当前系统上UID号为偶数的用户名和UID
[root@localhost ~]# awk -F: '{if($3%2==1) next;{printf "%-15s%d\n",$1,$3}}' /etc/passwd
• <19> 统计当前系统上以tcp协议工作的各端口的状态数
[root@localhost ~]# netstat -ant | awk '/^tcp/ {++STATE[$NF]} END {for(a in STATE) print a, STATE[a]}'
• <20>输出/etc/passwd中的每一行以||||隔开,默认不换行
[root@localhost ~]# awk -F: 'BEGIN{ORS="||||"}{print $0}' /etc/passwd