awk详解

一、什么是awk

​awk命名源自于它的三大作者名字的首字母,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。(gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展)。

​awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。

awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。

模式扫描和处理文件语言
awk擅长处理有规则的文本内容,例如 /etc/passwd 等,也可以完成信息的统计工作,擅长日志文件,配置文件、监控文件信息的处理
语法:
1.awk 选项 'BEGIN{}pattern{action}END{}' 文件路
2.standard output | awk 选项 'BEGIN{}pattern{action}END{}' 文件路
3.awk [options] -f awk-script-file filename

选项

-F[分隔符] -F: 与 -F ":"  等价
-F"  "  表示以空格为分隔符 默认不写-F就是以空格分割

awk的命令commands总共由三部分组成

BEGIN{}         		    {}                 END{}
读所有行之前做的事情       读一行处理一行 	   所有读完之后要做的事情

可以省略BEGIN{} 和END{},只进行{}行处理,并且{}行处理前可以加匹配,匹配成功后再处理

awk 'pattern' filename				示例:awk -F: '/root/' /etc/passwd		
awk '{action}' filename				示例:awk -F: '{print $1}' /etc/passwd			
awk 'pattern{action}' filename		示例:awk -F: '/root/{print $1,$3}' /etc/passwd		
								示例:awk 'BEGIN{FS=":"} /root/{print $1,$3}' /etc/passwd
其他命令 |awk 'pattern' 
其他命令 |awk '{action}'			
其他命令 |awk 'pattern{action}' 	

# 匹配pattern可以是:/正则表达式/也可以是条件,如下
示例:df -P |awk '$4 > 999999{print $0}'  # 也可以省略{print $0}

二、awk工作原理

awk -F: '{print $1,$3}' /etc/passwd
(1)awk会接收一行作为输入,并将这一行赋给awk的内部变量$0,每一行也可称为一个记录,行的边界是以换行符作为结束

(2)然后,刚刚读入的行被以:为分隔符分解成若干字段(或域),每个字段存储在已编号的变量中,编号从$1开始,最多达100个字段
注意:如果未指定行分隔符,awk将使用内置变量FS的值作为默认的行分隔符,FS默认值为空格

(3)使用print函数打印,如果$1$3之间没有逗号,它俩在输出时将贴在一起,应该在$1,$3之间加逗号,该逗号与awk的内置变量OFS是一致的,OFS默认为空格,于是以空格为分隔符输出$1和$3
我们可以指定:awk -F: ‘BEGIN{OFS="-"}{print $1,$3}’ /etc/passwd

(4)输出之后,将从文件中获取另一行,然后覆盖给$0,继续(2)的步骤将该行内容分隔成字段。。。继续(3)的步骤

  1. 读入一行文件,默认是以换行作符为读入分隔符的(RS),读入进来后,会赋值给$0,同时会为其编号赋值给NR变量;
  2. 检查FS变量是否有指定字段分隔符,按照字段分隔符拆分成列的形式,将每一列的内容赋值给对应的 $1 ,$2,$3 等内部变量。同时会将分隔后的总列数赋值给 NF变量;
  3. 输出内容,输出时候会使用print,$1,$3 这个逗号是输出字段分隔符,由OFS变量控制,默认是空;
  4. 输出内容默认是按照换行符展示,由ORS控制,控制输出行分隔符,默认是换行符;

三、记录与字段相关的内部变量

$0:保存当前行的内容				# awk -F: '{print $0}' /etc/passwd
NR:记录号,每处理完一条记录,NR值加1  # awk -F: '{print NR, $0}' /etc/passwd
NF:保存记录的字段数(多少列),$1,$2...$100	# awk -F: '{print $0,NF}' /etc/passwd

FS:输入字段分隔符,默认空格   
# awk -F: '/alice/{print $1, $3}' /etc/passwd
# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd	
# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd

OFS:输出字段分隔符 
# awk -F: '/root/{print $1,$2,$3,$4}' /etc/passwd
# awk -F: 'BEGIN{OFS="+++"} /^root/{print $1,$2,$3,$4}' /etc/passwd
# awk  'BEGIN{OFS="-";FS=":"}/root/{print NR,$0,NF}' /etc/passwd

RS: 输入行分隔符。默认回车换行
ORS: 输出行分隔符。默认为回车换行

练习:

[root@manager ~]# cat awk_file.txt 
ll 1990 50 51 61
kk 1991 60 52 62
hh 1992 70 53 63
jj 1993 80 54 64
mm 1994 90 55 65

3.1 FS指定分隔符

awk 通过内置变量,FS来指定字段分割符, 默认以空白行作为分隔符
1.输出文件中的第一列及行号

[root@manager ~]# awk '{print NR ,$1}' awk_file.txt 
1 ll
2 kk
3 hh
4 jj
5 mm

2.修改文件,然后指定多个分隔符,获取第一列内容

[root@manager ~]# cat awk_file.txt 
ll:1990 50 51 61
kk:1991 60 52 62
hh:1992 70 53 63
jj 1993 80 54 64
mm 1994 90 55 65

[root@manager ~]# awk  '{print $1}' awk_file.txt 
ll:1990
kk:1991
hh:1992
jj
mm

#以冒号或空格为分隔符
[root@manager ~]# awk -F '[: ]' '{print $2}' awk_file.txt 
1990
1991
1992
1993
1994

3.将多个分隔符视作一个处理

# 修改文件如下
[root@manager ~]# cat awk_file.txt 
ll:: 1990             50 51 61
kk:1991 60 52 62
hh::1992:      70 53 63
jj 1993 80 54   64
mm 1994             90 55 65

[root@manager ~]# awk -F '[: ]+' '{print $2}' awk_file.txt 
1990
1991
1992
1993
1994
[root@manager ~]# awk -F '[: ]+' '{print $1}' awk_file.txt 
ll
kk
hh
jj
mm

3.2 用NF获取最后一列

[root@manager ~]# awk '{print NF,$NF}' awk_file.txt  # 可以看出NF为常量吗$NF为最后一列
5 61
5 62
5 63
5 64
5 65

如果一个文件很长,靠数列数需要很长的时间,那如何快速打印倒数第二列

[root@manager ~]# awk '{print $(NF-1)}' awk_file.txt 
51
52
53
54
55

3.3 NR获取每行行号

[root@manager ~]# awk '{print NR,$0}' awk_file.txt 
1 ll 1990 50 51 61
2 kk 1991 60 52 62
3 hh 1992 70 53 63
4 jj 1993 80 54 64
5 mm 1994 90 55 65

打印第三行到第五行

[root@manager ~]# awk '3<=NR && NR<=5{print NR,$0}' awk_file.txt 
3 hh 1992 70 53 63
4 jj 1993 80 54 64
5 mm 1994 90 55 65

打印第三行和第五行

[root@manager ~]# awk '3==NR || NR==5{print NR,$0}' awk_file.txt 
3 hh 1992 70 53 63
5 mm 1994 90 55 65

打印第四行

[root@manager ~]# awk 'NR==4{print NR,$0}' awk_file.txt 
4 jj 1993 80 54 64

打印第三行和到第五行的第一列和第三列

[root@manager ~]# awk '3<=NR , NR<=5{print NR,$1,$3}' awk_file.txt 
3 hh 70
4 jj 80
5 mm 90

3.4 RS(Row Separate)读入行分隔符

awk 通过内置变量RS,对读入的文本进行分隔符指定;
1.准备文件内容

[root@manager ~]# cat file.txt 
Linux|Shell|Nginx--docker|Gitlab|jenkins--mysql|redis|mongodb

2.读入文件,并以--作为读入分隔符,然后将文件拆分为三列;

[root@manager ~]# awk 'BEGIN{RS="--"}{print $1}' file.txt 
Linux|Shell|Nginx
docker|Gitlab|jenkins
mysql|redis|mongodb

3.5 OFS输出字段分隔符

awk内置变量OFS(Output Filed Separte),输出字段分隔符,初始情况下OFS变量是空格。

[root@manager ~]# awk 'BEGIN{RS="--";FS="|";OFS=":"}{print $1,$3}' file.txt 
Linux:Nginx
docker:jenkins
mysql:mongodb

3.6 ORS输出行分隔符

awk内置变量ORS(Output Row Seprate),输出行分隔符,默认行分割符为\n

xxxxxxxxxxxx[root@manager ~]# awk 'BEGIN{RS="--";FS="|";OFS=":";ORS="##########"}{print $1,$3}' file.txt 
Linux:Nginx##########docker:jenkins##########mysql:mongodb

四、Awk格式输出Printf

awk 可以通过 printf 函数生成非常漂亮的数据报表。

4.1 printf 语法

格式符含义
%s打印字符串
%d打印十进制数(整数)
%f打印一个浮点数(小数)
%x打印十六进制数
修饰符含义
-左对齐
+右对齐

1.printf默认没有分隔符。

[root@manager ~]# awk -F ":" '{printf $1}' /etc/passwd
rootbindaemonadmlpsyncshutdownhaltmailoperatorgamesftp

2.加入换行,格式化输出。

[root@manager ~]# awk -F ":" '{printf "%s\n",$1}' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator
games
ftp

3.使用占位符美化输出。

[root@manager ~]# awk -F ":" '{printf "%10s %20s\n",$1,$NF}' /etc/passwd
      root            /bin/bash
       bin        /sbin/nologin
    daemon        /sbin/nologin
       adm        /sbin/nologin
        lp        /sbin/nologin
      sync            /bin/sync
  shutdown       /sbin/shutdown
      halt           /sbin/halt
      mail        /sbin/nologin
  operator        /sbin/nologin
     games        /sbin/nologin
       ftp        /sbin/nologin

4.默认右对齐,-表示左对齐。

[root@manager ~]# awk -F ":" '{printf "%-20s %-20s\n",$1,$NF}' /etc/passwd

4.2 示例1

格式化输出一个成绩表

[root@manager ~]# cat score.txt 
jack1 80 90 96 98
jack2 93 98 92 91
jack3 78 76 87 92
jack4 86 89 68 92
jack5 85 95 75 90
[root@manager ~]# awk 'BEGIN{printf "%-10s %-10s %-10s %-10s %-10s\n", \
"姓名","数学","语文","英语","政治"} \
{printf "%-12s %-12d %-12d %-12d %-12d\n",\
$1,$2,$3,$4,$5}' score.txt 
姓名         数学         语文         英语         政治        
jack1        80           90           96           98          
jack2        93           98           92           91          
jack3        78           76           87           92          
jack4        86           89           68           92          
jack5        85           95           75           90  

4.3 示例2

================print函数===================
[root@manager ~]#  date +%F | awk -F "-" '{print "年:",$1,"\n月:",$2,"\n日:",$3}': 2021: 10: 01

[root@manager ~]# awk -F: '{print "用户名:",$1,"用户id:",$3}' /etc/passwd

================printf函数===================
[root@manager ~]# awk -F: '{printf "用户名:%s 用户id:%s\n",$1,$3}' /etc/passwd
[root@manager ~]# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd

%s 字符类型
%d 数值类型
占15格的字符串
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n

五、 模式pattern与动作action

awk 'pattern{action}' filename
awk 第一种模式匹配:RegExp
awk 第二种模式匹配:运算匹配、布尔值匹配、数学运算符匹配

5.1.正则表达式

1.匹配包含root的行
awk -F: '/root/' /etc/passwd    

2.匹配 /etc/passwd 文件行中以 root 开头的行。
awk '/^root/'  /etc/passwd

3.匹配 /etc/passwd 文件行中 /bin/bash 结尾的行。
[root@manager ~]# awk "/\/bin\/bash/" /etc/passwd


# 匹配一行的某个字段
# awk '$0 ~ /^root/'  /etc/passwd
# awk '$1 ~ /^root/'  /etc/passwd
# awk '$7 !~ /bash$/'  /etc/passwd

5.2 比较表达式

比较表达式指的是使用关系运算符来比较数字以及字符串,只有当条件为真,才执行指定的动作

关系运算符
运算符			含义						示例
<				小于						  x<y
<=				小于或等于					x<=y
==				等于						  x==y
!=				不等于					     x!=y
>=				大于等于					x>=y
>				大于						  x>y
~				正则表达式匹配				   x~/y/
!~				正则表达式不匹配			  x!~/y/


示例:
# awk -F: '$3 == 0' /etc/passwd
# awk -F: '$3 < 10' /etc/passwd
# awk -F: '$7 == "/bin/bash"' /etc/passwd
# awk -F: '$1 == "root" ' /etc/passwd

5.3 条件表达式

# awk -F: '{if($3>300) {print $0}}' /etc/passwd
# awk -F: '{if($3>300) {print $3} else{print $1}}' /etc/passwd

# awk -F: '{if($3>300) {max=$3;print max} else{max=$1;print max}}' /etc/passwd
# awk -F: '{max=($3>300) ? $3 : $1; print max}' /etc/passwd

# awk -F: '{if($3>$4) {max=$3;print max} else{max=$4; print max}}' /etc/passwd
# awk -F: '{max=($3 > $4) ? $3: $4; print max}' /etc/passwd	
相当于:
if ($3 > $4)
	max=$3
else
	max=$4

5.3.1 单分支

1.以:为分隔符,打印当前管理员用户名称

[root@manager ~]# awk -F ':' '{if($3==0){print $1, "is adminisrator"}}' /etc/passwd

2.以:为分隔符,统计系统用户数量

[root@manager ~]# awk -F ':' '{if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
21

3.以:为分隔符,统计普通用户数量

[root@manager ~]# awk -F ':' '{if($3>=1000){i++}} END {print i}' /etc/passwd
8

4.以:为分隔符,只打印/etc/passwd中第3个字段的数值在50-100范围内的行

[root@manager ~]# awk -F ":" '{if($3>=50 && $3<=100){print $0}}' /etc/passwd

5.3.2 双分支

1.以:为分隔符,判断第三列如果等于0,则打印该用户名称,如果不等于0则打印第七列。

[root@manager ~]# awk -F ":" '{ if ($3==0) {print $1} else {print $7} }' /etc/passwd

2.以:为分隔符,判断第三列如果等于0,那么则打印管理员出现的个数,否则都视为系统用户,并打印它的个数

[root@manager ~]# awk -F ":" 'BEGIN { OFS="\n" } { if ($3==0) {i++} else {j++} } END { print i" 个管理员" , j" 个系统用户" }' /etc/passwd
1 个管理员
29 个系统用户

5.3.3 多分支

1.使用 awk if 打印出当前 /etc/passwd 文件管理员有多少个,系统用户有多少个,普通用户有多少个

方式1[root@manager ~]# awk 'BEGIN{FS=":";OFS="\n"} {if ($3==0) {i++} else if ($3>=200 && $3<1000) {j++} else {k++}} END { print i"个管理员",j"个 统用户",k"个普通用户"}' /etc/passwd
1个管理员
3个统用户
26个普通用户


方式2[root@manager ~]# cat count.awk 
BEGIN {
	FS=":"
	OFS="\n"
}
{
	if($3==0){
		i++
	} 
	else if($3>=200 && $3<1000) {
		j++
	} 
	else {
		k++
	}
}
END {
    	print   i "个管理员",j "个系统用户",k "个普通用户"
	}


[root@manager ~]# awk -f count.awk /etc/passwd
1个管理员
3个系统用户
26个普通用户

2.打印/etc/passwd文件中UID小于50的、或UID小于50大于100、或UID大于100的用户名以及UID

[root@manager ~]# cat count1.awk 
BEGIN {
	FS=":"
}

{
	if ($3<=50) {
	printf "%-20s%-20s%-10d\n","UID<50",$1,$3
	}
	else if($3>=50 && $3<100) {
	printf "%-20s%-20s%-10d\n","50<=UID<100",$1,$3

	} 
		
	else {
	printf "%-20s%-20s%-10d\n","UID>100",$1,$3
	}

}

[root@manager ~]# awk -f count1.awk /etc/passwd
UID<50              root                0         
UID<50              bin                 1         
UID<50              daemon              2         
UID<50              adm                 3         
UID<50              lp                  4     

5.4 算数运算

+ - * / %() ^(2^3)
可以在模式中执行计算,awk都将按浮点数方式执行算术运算

# awk -F: '$3 * 10 > 500' /etc/passwd

例:给4.2 加上一段平均成绩

方式1.
[root@manager ~]# cat score.awk 
BEGIN{
 	printf "%-10s %-10s %-10s %-10s %-10s %-10s\n","姓名","数学","语文","英语","政治","平均"
} 

{  	total=$2+$3+$4+$5 
	avg=total/(NF-1)
	printf "%-12s %-12d %-12d %-12d %-12d %-12d\n",$1,$2,$3,$4,$5,avg
}


[root@manager ~]# awk -f score.awk score.txt 
姓名         数学         语文         英语         政治         平均        
jack1        80           90           96           98           91          
jack2        93           98           92           91           93          
jack3        78           76           87           92           83          
jack4        86           89           68           92           83          
jack5        85           95           75           90           86   



方式2
[root@manager ~]# awk 'BEGIN{printf "%-10s %-10s %-10s %-10s %-10s %-10s\n","姓名","数学","语文","英语","政治","平均"} {total=$2+$3+$4+$5;avg=total/(NF-1);printf "%-12s %-12d %-12d %-12d %-12d %-12d\n",$1,$2,$3,$4,$5,avg }' score.txt 
姓名         数学         语文         英语         政治         平均        
jack1        80           90           96           98           91          
jack2        93           98           92           91           93          
jack3        78           76           87           92           83          
jack4        86           89           68           92           83          
jack5        85           95           75           90           86 

5.5 逻辑运算和复合模式

&&			逻辑与		a&&b
||			逻辑或		a||b
!			逻辑非		!a

示例:
# awk '$2 > 5 && $2 <= 15' filename
# awk '$3 == 100 || $4 > 50' filename
# awk '!($2 < 100 && $3 < 20)' filename

1.:为分隔符,匹配passwd文件中包含ftp或mail的行。
[root@manager ~]# awk -F ":" '$1=="ftp" || $1=="mail" {print $0}' /etc/passwd

2.:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。
[root@manager ~]# awk -F ":" '$3<50 && $4>50 {print $0}' /etc/passwd

3.匹配没有/sbin/nologin 的行。
[root@manager ~]# awk 'BEGIN{FS=":"} $0 !~ /\/sbin\/nologin/{print $0}' /etc/passwd

5.6 awk循环语句

循环主要包含for循环和while循环

5.6.1 while循环

while循环:while(条件表达式) 动作

[root@manager ~]# awk 'BEGIN{i=1;while(i<=10){print i; i++}}'
1
2
3
4
5
6
7
8
9
10

[root@manager ~]# awk -F: '{i=1; while(i<=NF) {print $i; i++}}' /etc/passwd # 将每一行分成七段,打印成七行

[root@manager ~]# awk -F: '{i=1; while(i<=10) {print $0;  i++}}' /etc/passwd		# 将每行打印10

有如下文件,用awk实现按列输出

[root@manager ~]# cat c.txt 
111 222
333 444 555
666 777 888 999
[root@manager ~]# 

[root@manager ~]# cat c.txt | xargs -n1
111
222
333
444
555
666
777
888
999


方式1.
[root@manager ~]# awk '{i=1;while(i<=NF){print $i;i++}}' c.txt 
111
222
333
444
555
666
777
888
999


方式2.
[root@manager ~]# cat print.awk 
{
	i=1  # 末尾加不加分号都行
	while(i<=NF){
		print $i
		i++
	}
}
[root@manager ~]# awk -f print.awk c.txt 
111
222
333
444
555
666
777
888
999

5.6.2 for 循环

[root@manager ~]# awk 'BEGIN{for(i=1;i<=5;i++) {print i}}'
1
2
3
4
5


[root@manager ~]# awk -F ':' '{for(i=1;i<=10;i++){print $0}}' /etc/passwd # 每行打印十次

[root@manager ~]# awk -F ':' '{for(i=1;i<=NF;i++){print $i}}' /etc/passwd # 每行分成七列,打印成七行

需求:计算1+2+3+4+…+100的和,请使用while、for两种循环方式实现

[root@manager ~]# awk 'BEGIN{for(i=1;i<=100;i++){sum+=i} print sum}' 
5050

或者
[root@manager ~]# cat sum_for.awk 
BEGIN {
	for(i=1;i<=100;i++)
		{
			sum+=i
		}
		print sum	
}

[root@manager ~]# awk -f sum_for.awk 
5050



[root@manager ~]# awk 'BEGIN{i=1;while(i<=100){sum+=i;i++}print sum}'
5050

或者
[root@manager ~]# cat while_sum.awk 
BEGIN {
	i=1
	while (i<=100)
	{
		sum+=i
		i++
	}
	print sum
}

[root@manager ~]# awk -f while_sum.awk 
5050

六、awk数组

6.1 什么是awk数组

数组其实也算是变量, 传统的变量只能存储一个值,但数组可以存储多个值。
awk不区分 关联数组与普通数组;

6.2 awk数组应用场景

通常用来统计、比如:统计网站访问TOP10、网站URL访问TOP10等等等

6.3 awk数组统计技巧

  1. 在awk中,使用数组时,不仅可以使用1 2 3 …n作为数组索引,也可以使用字符串作为数组索引。
  2. 要统计某个字段的值,就将该字段作为数组的索引,然后对索引进行遍历。
    1.统计谁就将谁作为索引的名称;
    2.然后让其相同的进行自增;
    3.遍历索引名称,获取对应出现的值,也就是次数;

七、 综合应用

7.1 根据文件内容查找出指定行信息

  1. 找出/etc/passwd 中包含root的行
    /文件内容/ //里面可以写正则表达式
    [root@localhost ~]# awk '/root/{print $0}' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    
    或者
    [root@localhost ~]# awk '/root/' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    

工作流程

awk -F: '{print $1,$3}' /etc/passwd
​
1、awk会读取文件的一行内容然后赋值给$0
2、然后awk会以-F指定的分隔符将该行切分成n段,最多可以达到100段,第一段给$1,第二段给$2,依次次类推
3、print输出该行的第一段和第三段,逗号代表输出分隔符,默认与-F保持一致
4、重复步骤1,2,3直到文件内容读完

内置变量

$0 表示一整行内容
NR 记录号,等同于行号
NF 以-F指定的分隔符分割的段数

7.2 根据行号查找出指定信息

注:打印一行所有信息用$0

[root@localhost dev]# awk -F: 'NR == 1{print $1,$3}' /etc/passwd  # 定位到第一行 打印出第一列与第三列
root 0
[root@localhost dev]# awk -F: 'NR == 3{print $1,$3}' /etc/passwd   # 定位到第三行,打印出地一列与第三列
daemon 2
[root@localhost dev]# awk -F: 'NR>=3 && NR<=5{print $1,$3}' /etc/passwd  # 定位第三行到第五行,打印
daemon 2
adm 3
lp 4
[root@localhost dev]# awk -F: 'NR<=3 || NR>=22{print $1,$3}' /etc/passwd # 定位大于22或者小于三的行
root 0
bin 1
daemon 2
ntp 38
tcpdump 72
ldap 55
nginx 997
apache 48
    
[root@localhost dev]# awk -F: '/nologin$/{print $0}' /etc/passwd #匹配以nologin结尾的行,打印整行,&0代表整行

[root@localhost dev]# awk -F: 'NR>=3 && NR<=5 {print $0}' /etc/passwd # 打印三到五行完整的行
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@localhost dev]# awk  'NR>=3 && NR<=5 {print $0}' /etc/passwd # 同上
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@localhost dev]# awk -F: '$6 ~ /root/{print $0}' /etc/passwd # 正则过滤第六段包含root的行,打印出整行, /^root$/表示第六段为root
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

[root@localhost dev]# awk -F: '$6 !~ /root/{print $0}' /etc/passwd # 正则过滤第六段不包含root的行,打印出整行

[root@localhost dev]# awk -F: '$1=="root"{print $0}' /etc/passwd # 匹配第一段为root的行,打印整行
root:x:0:0:root:/root:/bin/bash


[root@localhost dev]# awk -F: '/^root/{print $0}' /etc/passwd # 以root开头的行
root:x:0:0:root:/root:/bin/bash 
前三行中第一段为root的行打印出来
[root@localhost ~]# awk -F: 'NR>=1 && NR<=3 && $1=="root"{print $0}' a.txt
root:x:0:0:root:/root:/bin/bash
[root@localhost ~]# 

将eth0网卡的ip地址取出来
[root@localhost ~]# ifconfig eth0 | awk -F" " 'NR==2{print $2}'
192.168.138.101
[root@localhost ~]# ifconfig eth0 | awk  'NR==2{print $2}' # 不指定F参数默认以空格为分隔符
192.168.138.101
[root@localhost ~]# 

按照多个符号切分 例如按照:或者空格切分
有一下文件

[root@localhost ~]# cat a.txt 
tom  1 18:male:50000
lili 2 20:famale:6000
jack 3 25:male:7500

取出第一列和最后一列


[root@localhost ~]# awk -F "[ :]+" '{print $1,$NF}' a.txt   # +表示贪婪匹配,防止多个空格
tom 50000
lili 6000
jack 7500

替换
gsub(/要替换的信息/"替换成什么信息",将第几列信息替换)

[root@localhost ~]# awk 'gsub(/:/,"¥",$3)' a.txt 
tom 1 18¥male¥50000
lili 2 20¥famale¥6000
jack 3 25¥male¥7500

取ip地址

[root@localhost ~]# ifconfig ens32 | awk -F "[/ ]+" 'NR==2{print $3}'
10.0.0.100

八、awk高级使用方法

BEGIN

1.在处理文件之前做什么操作动作

[root@localhost ~]# awk 'BEGIN{print "人员名称:"}{print $1}' a.txt 
人员名称:
tom
lili
jack

2.可实现计算器功能

[root@localhost ~]# awk 'BEGIN{30+40}'
[root@localhost ~]# awk 'BEGIN{print 30+40}'
70
[root@localhost ~]# awk 'BEGIN{print 30/40}' # 除
0.75
[root@localhost ~]# awk 'BEGIN{print 2^8}'  # 幂
256
[root@localhost ~]# awk 'BEGIN{print 5%3}' # 取余
2

ENG:

1.在处理文件之后做什么操作
2.将统计运算结果进行输出

[root@localhost ~]# awk 'END{print "人员名称:"}{print $1}' a.txt 
tom
lili
jack
人员名称:

内置变量: NF NR

NF参数:分的段的总数

[root@localhost ~]# awk -F: 'NR<=5{print $NF}' /etc/passwd  # 取出前五行的最后一段
/bin/bash
/sbin/nologin
/sbin/nologin
/sbin/nologin
/sbin/nologin
[root@localhost ~]# awk -F: 'NR<=5{print $(NF-1)}' /etc/passwd # 取出前五行倒数第二段
/root
/bin
/sbin
/var/adm
/var/spool/lpd

[root@localhost ~]# awk -F: 'NR<=5{print NR, $(NF-1)}' /etc/passwd # 加上行号
1 /root
2 /bin
3 /sbin
4 /var/adm
5 /var/spool/lpd
[root@localhost ~]# 
[root@localhost ~]# cat a.txt 
tom  1 18:male:50000
jack 2 20:famale:6000
tom  1 18:male:50000
tom  1 18:male:50000
tom  1 18:male:50000
tom  1 18:male:50000
jack 2 20:famale:6000
jack 2 20:famale:6000
mary 2 20:famale:6000
jack 2 20:famale:6000
tom  1 18:male:50000
jack 2 20:famale:6000
mary  1 18:male:50000
tom  1 18:male:50000
tom  1 18:male:50000
tom  1 18:male:50000
jack 2 20:famale:6000
jack 2 20:famale:6000
jack 2 20:famale:6000
mary 2 20:famale:6000
jack 2 20:famale:6000
jack 2 20:famale:6000

统计算法:
统计出 mary出现的次数
i=i+1

[root@localhost ~]# awk '$1~/mary/{i=i+1;print i}' a.txt 
1
2
3

[root@localhost ~]# awk '$1~/mary/{i=i+1}END{print i}' a.txt 
3

求和累加算法:
求所有人的工资和
i+$n

[root@localhost ~]# awk -F: '{i=i+$NF}END{print i}' a.txt 
572000

总共有100000万,发完所有人的工资还剩多少

[root@localhost ~]# awk -F: 'BEGIN{i=1000000}{i=i-$NF}END{print i}' a.txt 
428000

已知一个变量 msg="I am a teacher, my name is jack",打印字符长度小于3的单词

# 方式一:
[root@manager ~]# for i in $msg;do [ ${#i} -lt 3 ] && echo $i;done
I
am
a
my
is

# 方式二:
[root@manager ~]# echo $msg |xargs -n1 |awk '{if(length<3) print}'
I
am
a
my
is

# 方式三:
[root@manager ~]# echo $msg |awk '{for(i=1;i<=NF;i++) {if(length($i)<3) {print $i} } }'
I
am
a
my
is

# 方式四:
[root@manager ~]# echo $msg |egrep -wo '[a-zA-Z]{1,3}'
I
am
a
my
is

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值