shell编程之awk

九、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,…

要点:

  1. 各项目之间使用逗号隔开,而输出时则以空白字符分隔;
  2. 输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;
  3. 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 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值