14.Linux四剑客之awk文本处理工具

2021-07-04 分类:Linux基础, shell编程 阅读(550) 评论(0)

孙富阳, 江湖人称没人称。多年互联网运维工作经验,曾负责过孙布斯大规模集群架构自动化运维管理工作。擅长Web集群架构与自动化运维,曾负责国内某大型博客网站运维工作。

1.Awk基础介绍

1.什么是awk

awk不仅仅是一个文本处理工具,通常用于处理数据并生成结果报告。当然awk也是一门编程语言,是linux上功能最强大的数据处理工具之一。

2.awk语法格式

第一种形式:awk 'BEGIN{} pattern {commands} END {}' file_name
第二种形式:standard output|awk BEGIN{} pattern {commands} END {}
第三种形式:awk [options] -f awk-script-file filenames

语法格式含义
BEGIN {}正式处理数据之前执行
pattern匹配模式
{commands}处理命令,可能多行
END{}处理完所有匹配数据后执行
含义解释:BEGIN发现在读文件之前,所有会在处理之前就执行了。{}表示处理文件的过程,由于文件内有三行,所以会执行三次print。END{}表示文件处理完毕后的动作。

2.Awk工作原理

# awk -F: '{print $1,$3}' /etc/passwd 
1.awk将文件中的每一行作为输入, 并将每一行赋给内部变量$0, 以换行符结束
2.awk开始进行字段分解,每个字段存储在已编号的变量中,从$1开始[默认空格分割]
3.awk默认字段分隔符是由内部FS变量来确定, 可以使用-F修订
4.awk行处理时使用了print函数打印分割后的字段
5.awk在打印后的字段加上空格,因为$1,$3之间有一个逗号。逗号被映射至OFS内部变量中,称为输出字段分隔符,OFS默认为空格.
6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕.

3.Awk内部变量

内置变量含义
$0整行内容
$1-$n当前行的第1-n个字段
NF当前行的字段个数,也就是多少列
NR当前的行号,从1开始计数
FS输入字段分隔符。不指定默认以空格或tab键分割
RS输入行分隔符。默认回车换行
OFS输出字段分隔符。默认为空格
ORS输出行分隔符。默认为回车换行
要想了解awk的一些内部变量需要先准备如下数据文件。
[root@test ~]# cat >> awk_file.txt << EOF
> 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
> EOF
[root@test ~]# 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

1. $0保存当前记录的内容

[root@test ~]# awk '{print $0}' 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

2. FS指定字段分割符, 默认以空白行作为分隔符

#1.输出文件中的第一列
[root@test ~]#  awk '{print $1}' awk_file.txt
ll
kk
hh
jj
mm
#2.指定多个分隔符,获取第一列内容
#以冒号或空格为分隔符
[root@test ~]# awk -F '[: ]' '{print $2}' awk_file.txt
1990
1991
1992
1993
1994 
#[: ]+连续的多个冒号当一个分隔符,连续的多个空格当一个分隔符,连续空格和冒号也当做一个字符来处理
[root@test ~]# awk -F '[: ]+' '{print $2}' awk_file.txt
1990
1991
1992
1993
1994

3. NF,保存每行的最后一列

#1.通过print打印,NF和$NF,你发现了什么?
[root@test ~]# awk '{print NF,$NF}' awk_file.txt
5 61
5 62
5 63
5 64
5 65 
#F: 如果将第五行的65置为空,那么该如何在获取最后一列的数字?
[root@test ~]# awk '{print $5}' awk_file.txt
61
62
63
64
    #最后一列为空,为什么?  
#Q.使用$NF为什么就能成功?(因为NF变量保存的是每一行的最后一列)
[root@test ~]# awk '{print $NF}' awk_file.txt
61
62
63
64
65
#2.如果一个文件很长,靠数列数需要很长的时间,那如何快速打印倒数第二列?
[root@test ~]# awk '{print $(NF-1)}' awk_file.txt
51
52
53
54
90

4.awk内置变量NR,表示记录行号。

#1.使用pring打印NR,会发现NR会记录每行文件的行号
[root@test ~]# 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
#2.那如果我们想打印第二行到第三行的内容怎么办?
[root@test ~]# awk 'NR>1&&NR<4 {print NR,$0}' awk_file.txt
2 kk 1991 60 52 62
3 hh 1992 70 53 63 
#3.那如果只想打印第三行,该怎么办?
[root@test ~]# awk 'NR==3 {print NR,$00}' awk_file.txt
3 hh 1992 70 53 63 
#4.那如果既想打印第三行,又想打印第一列?
[root@test ~]# awk 'NR==3 {print NR,$1}' awk_file.txt
3 hh

5.RS,读入行分隔符。

[root@test ~]# cat >> file.txt << EOF
> Linux|Shell|Nginx--docker|Gitlab|jenkins--mysql|redis|mongodb
> EOF
[root@test ~]# cat file.txt 
Linux|Shell|Nginx--docker|Gitlab|jenkins--mysql|redis|mongodb
[root@test ~]# awk 'BEGIN{RS="--"}{print $0}' file.txt
Linux|Shell|Nginx
docker|Gitlab|jenkins
mysql|redis|mongodb

6. “OFS输出字段分隔符”,初始情况下OFS变量是空格。

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

7. “ORS输出行分隔符”,默认行分割符为\n

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

4.Awk格式输出

awk可以通过printf函数生成非常漂亮的数据报表。
格式符含义
%s打印字符串
%d打印十进制数(整数)
%f打印一个浮点数(小数)
%x打印十六进制数
修饰符含义
-左对齐
+右对齐

1.printf默认没有分隔符。

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

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

[root@test ~]# awk 'BEGIN{FS=":"}{printf "%s\n",$1}' /etc/passwd
root
bin
daemon
adm
lp
sync

3.使用占位符美化输出

[root@test ~]# awk 'BEGIN{FS=":"} {printf "%20s%20s\n",$1,$7}' /etc/passwd
                root           /bin/bash
                 bin       /sbin/nologin
              daemon       /sbin/nologin
                 adm       /sbin/nologin
                  lp       /sbin/nologin
                sync           /bin/sync
            shutdown      /sbin/shutdown

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

[root@test ~]#awk 'BEGIN{FS=":"}{printf "%-20s %-20s\n",$1,$7}' /etc/passwd
root                 /bin/bash           
bin                  /sbin/nologin       
daemon               /sbin/nologin       
adm                  /sbin/nologin       
lp                   /sbin/nologin       
sync                 /bin/sync 

5.美化一个成绩表

[root@test ~/2021-07-02]# cat student.txt 
xu 80 56 46
wang 49 56 76
sun 47 76 67
guo 56 77 78
liu 65 45 87
zhang 76 74 87
#效果
[root@test ~/2021-07-02]# awk 'BEGIN{printf "%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu"}{printf "%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4}' student.txt 
name      yuwen     shuxue    yingyu    
xu        80        56        46        
wang      49        56        76        
sun       47        76        67        
guo       56        77        78        
liu       65        45        87        
zhang     76        74        87
#####将命令写进文件使用-f调用
[root@test ~/2021-07-02]# cat student.awk 
BEGIN{
	printf "%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu"
}
{
	printf "%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4
}
[root@test ~/2021-07-02]# awk -f student.awk student.txt 
name      yuwen     shuxue    yingyu    
xu        80        56        46        
wang      49        56        76        
sun       47        76        67        
guo       56        77        78        
liu       65        45        87        
zhang     76        74        87

5.Awk模式匹配(过滤)

awk第一种模式匹配:RegExp
awk第二种模式匹配:关系运算匹配

1.RegExp示例

1.1匹配/etc/passwd文件行中含有root字符串的所有行。
[root@test ~/2021-07-02]# awk 'BEGIN{FS=":"}/root/{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
dockerroot:x:997:994:Docker User:/var/lib/docker:/sbin/nologin 
1.2.匹配/etc/passwd文件行中以root开头的行。
[root@test ~/2021-07-02]# awk '/^root/{print $0}' passwd
root:x:0:0:root:/root:/bin/bash 
1.3.匹配/etc/passwd文件行中/bin/bash结尾的行。
[root@test ~/2021-07-02]# awk '/\/bin\/bash$/{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
www:x:1000:1000::/home/www:/bin/bash

2.运算符匹配示例

符号含义
<小于
大于
<=小于等于
>=大于等于
==等于
!=不等于
~匹配正则表达式
!~不匹配正则表达式
2.1以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息
[root@test ~/2021-07-02]# awk 'BEGIN{FS=":"}$3<50{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin 
2.2以:为分隔符,匹配/etc/passwd文件中第3个字段大于50的所有行信息
[root@test ~/2021-07-02]# awk 'BEGIN{FS=":"}$3>50{print $0}' passwd
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin 
2.3以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息
[root@test ~]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
www:x:1000:1000::/home/www:/bin/bash
2.4以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息
[root@test ~]# awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' passwd
bin:x:1:1:bin:/bin:/sbin/nologin
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 
2.5以:为分隔符,匹配/etc/passwd文件中第3个字段包含3个数字以上的所有行信息
[root@test ~]# awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{print $0}' passwd
systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin
polkitd:x:999:998:User for polkitd:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
nginx:x:998:996:nginx user:/var/cache/nginx:/sbin/nologin
dockerroot:x:997:994:Docker User:/var/lib/docker:/sbin/nologin
www:x:1000:1000::/home/www:/bin/bash

3.布尔运算符匹配与或非示例

符号含义
||
&&     
!
3.1以:为分隔符,匹配passwd文件中包含ftp或mail的所有行信息。
[root@test ~]# awk 'BEGIN{FS=":"}$1=="ftp" || $1=="mail" {print $0}' passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin 
#####还可以这样写
[root@test ~]# awk 'BEGIN{FS=":"}$1~/ftp|mail/ {print $0}' passwd
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
3.2以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息。
[root@test ~]# awk 'BEGIN{FS=":"}$3<50 && $4>50{print $0}' passwd
games:x:12:100:games:/usr/games:/sbin/nologin 
3.3匹配没有/sbin/nologin 的行。
[root@test ~]#awk 'BEGIN{FS=":"}$0!~/\/sbin\/nologin/{print $0}' passwd
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
www:x:1000:1000::/home/www:/bin/bash

4.运算符匹配示例

运算符含义
+
-
*
/
%
计算学生课程分数平均值
学生课程文件内容如下:
[root@test ~/2021-07-02]# cat student.txt 
xu 80 56 46
wang 49 56 76
sun 47 76 67
guo 56 77 78
liu 65 45 87
zhang 76 74 87 
#1.输出平均值
[root@test ~/2021-07-02]# awk 'BEGIN{printf "%-10s%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu","pingjun"}{printf "%-10s%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4,$1+$2+$3+$4}' student.txt 
#2.执行观察结果
name      yuwen     shuxue    yingyu    pingjun   
xu        80        56        46        182       
wang      49        56        76        181       
sun       47        76        67        190       
guo       56        77        78        211       
liu       65        45        87        197       
zhang     76        74        87        237
######是不是看着很乱???我们将他写进文件里
[root@test ~/2021-07-02]# cat student2.awk 
BEGIN{
	printf "%-10s%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu","pingjun"
}
{
	printf "%-10s%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4,$1+$2+$3+$4
}
#然后执行看看效果
[root@test ~/2021-07-02]# awk -f student2.awk student.txt 
name      yuwen     shuxue    yingyu    pingjun   
xu        80        56        46        182       
wang      49        56        76        181       
sun       47        76        67        190       
guo       56        77        78        211       
liu       65        45        87        197       
zhang     76        74        87        237
统计各学科平均分
[root@test ~/2021-07-02]# awk 'BEGIN{printf "%-10s%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu","total"}{printf "%-10s%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4,$2+$3+$4;yuwen=$2+yuwen;shuxue=$3+shuxue;yingyu=$4+yingyu;total=$2+$3+$4+total}END{printf "%-10s%-10s%-10s%-10s%-10s\n","pingjun",yuwen/NR,shuxue/NR,yingyu/NR,total/NR}' student.txt 
name      yuwen     shuxue    yingyu    total     
xu        80        56        46        182       
wang      49        56        76        181       
sun       47        76        67        190       
guo       56        77        78        211       
liu       65        45        87        197       
zhang     76        74        87        237       
pingjun   62.1667   64        73.5      199.667
####写到文件里
[root@test ~/2021-07-02]# cat student3.awk 
BEGIN{
	printf "%-10s%-10s%-10s%-10s%-10s\n",\
	"name","yuwen","shuxue","yingyu","total"
}

{
	printf "%-10s%-10s%-10s%-10s%-10s\n",\
	$1,$2,$3,$4,$2+$3+$4;
	yuwen=$2+yuwen;
	shuxue=$3+shuxue;
	yingyu=$4+yingyu;
	total=$2+$3+$4+total
}

END{
	printf "%-10s%-10s%-10s%-10s%-10s\n","pingjun",yuwen/NR,shuxue/NR,yingyu/NR,total/NR
}

6.Awk条件判断

1.if语句格式:

{ if(表达式){语句;语句;... } }
1.打印当前管理员用户名称
[root@test ~]# awk -F: '{ if($3==0){print $1,"is admin"} }' /etc/passwd
root is admin 
2.统计系统用户数量
[root@test ~]# awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd
24 

2.if...else 语句格式:

{if(表达式){语句;语句;... }else{语句;语句;...}}
1.判断第三列如果等于0,则打印该用户名称,如果不等于0则打印第七列。
[root@test ~]# awk 'BEGIN{FS=":"} { if ($3==0) { print $1 } else { print $7 }}' /etc/passwd 
2.判断第三列如果等于0,那么则打印管理员出现的个数,否则都视为系统用户,并打印它的个数。
[root@test ~]# awk 'BEGIN{FS=":";OFS="\n"} { if($3==0) { i++ } else { j++ } } END { print i" 个管理员" , j" 个系统用户" }' /etc/passwd
1 个管理员
26 个系统用户

3.if...else if...else 语句格式:

{ if(表达式 1){语句;语句;... }else if(表达式 2){语句;语句;. .. }else{语句;语句;... }}
1.使用awk if打印出当前/etc/passwd文件管理员有多少个,系统用户有多少个,普通用户有多少个
[root@test ~]# awk -F: '{ if($3==0){i++} else if($3>0 && $3<1000){j++} else if($3>=1000) {k++}} END {print "管理员个数"i; print "系统用户个数" j; print "系统用户个数"k }' /etc/passwd
管理员个数1
系统用户个数24
系统用户个数2 
#############或者写在文件里比较清晰
[root@test ~/2021-07-02]# cat passwd_conent.awk 
#行处理前
BEGIN{
    print "开始统计";
	FS=":"
}
#行处理中
{
    if($3==0)
        { i++ }
    else if ($3>0 && $3<1001)
        { j++ }
    else
        { k++ }
}
#行处理后
END {
    print i" 个管理员";
    print j" 个系统用户";
    print k" 个普通用户"
}
[root@test ~/2021-07-02]# awk -f passwd_conent.awk passwd
开始统计
1 个管理员
25 个系统用户
1 个普通用户
2.打印/etc/passwd文件中UID小于50的、或者UID小于50大于100、或者UID大于100的用户名以及UID。
[root@test ~/2021-07-02]# cat if.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
    }
}
3.计算下列每个同学的总分,并且只打印平均分数大于200的同学姓名和分数信息
[root@test ~/2021-07-02]# cat student.txt 
xu 80 56 46
wang 49 56 76
sun 47 76 67
guo 56 77 78
liu 65 45 87
zhang 76 74 87
[root@test ~/2021-07-02]# cat student2.awk 
BEGIN{
	printf "%-10s%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu","total"
}
{
	if (($1+$2+$3+$4)>200)
	printf "%-10s%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4,$1+$2+$3+$4
}
[root@test ~/2021-07-02]# awk -f student2.awk student.txt 
name      yuwen     shuxue    yingyu    total     
guo       56        77        78        211       
zhang     76        74        87        237
4.统计Nginx的状态,请分别打印出200类、300类、400类、的状态码出现了多少次。
[root@test ~/2021-07-02]# cat access.awk 
{
if ( $9 ~ /^2/ )
{ i++ }
else if ( $9 ~ /^3/ )
{ b++ } 
else if ( $9 ~ /^4/ )
{ c++ }
}
END{
 print "200系列" i 
 print "300系列" b
 print "400系列" c
}
[root@test ~/2021-07-02]# awk -f access.awk access.log 
200系列142666
300系列19647
400系列4623

7.Awk循环语句

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

[root@test ~]# awk 'BEGIN{ i=1; while(i<=10){print i; i++} }'
[root@test ~]# awk -F: '{i=1; while(i<=NF){print $i; i++}}' /etc/passwd
[root@test ~]# awk -F: '{i=1; while(i<=10) {print $0; i++}}' /etc/passwd
[root@test ~]# cat>> b.txt << EOF
> 111 222
> 333 444 555
> 666 777 888 999
> EOF
[root@test ~]# cat b.txt 
111 222
333 444 555
666 777 888 999
[root@test ~]# awk '{i=1; while(i<=NF){print $i; i++}}' b.txt
111
222
333
444
555
666
777
888
999
1.While循环打印99乘法表
[root@test ~]# seq 9|awk '{i=NR;while(i<=NR) {for(b=1;b<=i;b++){printf i"*"b"="i*b" "}{print "\n"};i++}}'
1*1=1 
2*1=2 2*2=4 
3*1=3 3*2=6 3*3=9 
4*1=4 4*2=8 4*3=12 4*4=16 
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81 
[root@test ~]# seq 1|awk '{i=1;while(i<=9) {for(b=1;b<=i;b++){printf i"*"b"="i*b" "}{print "\n"};i++}}'
1*1=1 
2*1=2 2*2=4 
3*1=3 3*2=6 3*3=9 
4*1=4 4*2=8 4*3=12 4*4=16 
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25 
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36 
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49 
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64 
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
2.While循环统计各学科平均分
[root@test ~/2021-07-02]# cat student.txt 
xu 80 56 46
wang 49 56 76
sun 47 76 67
guo 56 77 78
liu 65 45 87
zhang 76 74 87
#########################
[root@test ~]# awk 'BEGIN{printf "%-10s%-10s%-10s%-10s%-10s\n","name","yuwen","shuxue","yingyu","total"}{i=NR;while(i<=NR){printf "%-10s%-10s%-10s%-10s%-10s\n",$1,$2,$3,$4,$2+$3+$4;yuwen=$2+yuwen;shuxue=$3+shuxue;yingyu=$4+yingyu;total=$2+$3+$4+total;i++}}END{printf "%-10s%-10s%-10s%-10s%-10s\n","pingjun",yuwen/NR,shuxue/NR,yingyu/NR,total/NR}' student.txt
name      yuwen     shuxue    yingyu    total     
xu        80        56        46        182       
wang      49        56        76        181       
sun       47        76        67        190       
guo       56        77        78        211       
liu       65        45        87        197       
zhang     76        74        87        237       
pingjun   62.1667   64        73.5      199.667
#####################太乱了啊
[root@test ~/2021-07-02]# awk -f student_xunhuan.awk student.txt 
name      yuwen     shuxue    yingyu    total     
xu        80        56        46        182       
wang      49        56        76        181       
sun       47        76        67        190       
guo       56        77        78        211       
liu       65        45        87        197       
zhang     76        74        87        237       
pingjun   62.1667   64        73.5      199.667
###########使用循环是不是多此一举了?直接使用变量不好吗
[root@test ~/2021-07-02]# cat student3.awk 
BEGIN{
	printf "%-10s%-10s%-10s%-10s%-10s\n",\
	"name","yuwen","shuxue","yingyu","total"
}

{
	printf "%-10s%-10s%-10s%-10s%-10s\n",\
	$1,$2,$3,$4,$2+$3+$4;
	yuwen=$2+yuwen;
	shuxue=$3+shuxue;
	yingyu=$4+yingyu;
	total=$2+$3+$4+total
}

END{
	printf "%-10s%-10s%-10s%-10s%-10s\n","pingjun",yuwen/NR,shuxue/NR,yingyu/NR,total/NR
}
[root@test ~/2021-07-02]# awk -f student3.awk  student.txt 
name      yuwen     shuxue    yingyu    total     
xu        80        56        46        182       
wang      49        56        76        181       
sun       47        76        67        190       
guo       56        77        78        211       
liu       65        45        87        197       
zhang     76        74        87        237       
pingjun   62.1667   64        73.5      199.667

2.for循环:for(初始化计数器;计数器测试;计数器变更) 动作

#C 风格 for
[root@test ~/2021-07-02]# awk 'BEGIN{for(i=1;i<=5;i++){print i} }'
1
2
3
4
5 
#将每行打印 10 次
[root@test ~]# awk -F: '{ for(i=1;i<=10;i++) {print $0} }' passwd
需求:计算1+2+3+4+...+100的和,请使用while、for两种循环方式实现
# while循环
[root@test ~/2021-07-02]# cat while_add.awk 
BEGIN{
    while(i<=100)
    {# 一个变量不赋值,默认为0或者空
        sum+=i
        i++
    }    
	print sum
}
[root@test ~/2021-07-02]# awk -f while_add.awk
5050
# for循环 
[root@test ~/2021-07-02]# cat for_add.awk 
BEGIN{
    for(i=0;i<=100;i++) 
    {
        sum+=i
    }
        print sum
}
[root@test ~/2021-07-02]# awk -f for_add.awk
5050

8.awk文本替换gsub

[root@test ~/2021-07-02]# cat reg.txt 
sun zhang liu wang
sun liu zhang wang
sun zhang wang liu zhang
sun liu wang zhang
sun wang liu zhang
sun wang zhang liu
zhang sun wang liu
zhang sun liu wang
zhang wang sun liu
zhang wang liu sun
zhang liu sun wang
zhang liu wang sun
#####只匹配zhang显示的结果
[root@test ~/2021-07-02]# awk '/zhang/{gsub(/zhang/,"$");print $0}' reg.txt
sun $ liu wang
sun liu $ wang
sun $ wang liu $
sun liu wang $
sun wang liu $
sun wang $ liu
$ sun wang liu
$ sun liu wang
$ wang sun liu
$ wang liu sun
$ liu sun wang
$ liu wang sun
####$2匹配张显示的结果
[root@test ~/2021-07-02]# awk '$2~/zhang/{gsub(/zhang/,"$");print $0}' reg.txt
sun $ liu wang
sun $ wang liu $
####$2匹配zhang,并且只替换第二列的内容
[root@test ~]#awk '$2~/zhang/{gsub(/zhang/,"$",$2);print $0}' reg.txt
sun $ liu wang
sun $ wang liu zhang

评论已关闭

登录

忘记密码 ?

切换登录

注册

鲁ICP备2021019243号-1