三剑客之 awk

-三剑客之 awk

1、什么是awk,主要作用是什么?

主要用来处理文本,将文本按照指定格式输出
多数处理列

2、awk的格式

1.awk [参数] '匹配规则、处理规则' [处理文本路径] 
	[root@localhost ~]# awk -F: '{print $1}' /etc/passwd
		 					 必须是''$1:代表第一列, $2:第二列 一次类推   $0:代表每次读取的行
	[root@localhost ~]# awk -F: '{print $(NF-1)}' /etc/passwd
NF:倒数第一列   NF-1:倒数第二列 要加()     NF-2:倒数第三列 要加() 
匹配规则主要是正则表达式 可以不写 直接执行处理规则包括如下:
	字符串
	正则表达式

处理规则设置变量、设置数组、数组循环、+-*/等一系列操作包括如下:
	BEGIN{}			:awk处理文件之前执行    所有变量定义都应该放在BEGIN里面
	//				:读取文件之后使用的匹配规则
	{}				:循环,每次处理一行
	NED{}			:awk处理文件之后执行

2.流式输出也叫(标准输出) | awk [参数] '匹配规则、处理规则'
	[root@localhost ~]# cat /etc/passwd | awk -F: '{print $1}'
案例:
		
	案例1:把/etc/passwd中的包含root的行打印出来	
		[root@localhost ~]# awk -F: '/root/' /etc/passwd	
         root:x:0:0:root:/root:/bin/bash
		operator:x:11:0:operator:/root:/sbin/nologin	
	案例2:把/etc/passwd中以root开头的行打印出来
        [root@localhost ~]# awk -F: '/^root/' /etc/passwd
        root:x:0:0:root:/root:/bin/bash
	案例3:将/etc/passwd中匹配第三列和第五列的数据
        [root@localhost ~]# awk -F: '{print $3, $5}' /etc/passwd
        0 root
        1 bin
        2 daemon
        3 adm
        4 lp
        5 sync
        6 shutdown
    		
	案例4:打印以root或者ftp开头的行的解析器
        [root@localhost ~]# awk -F: '/^root|^ftp/ {print $NF}' /etc/passwd
        /bin/bash
        /sbin/nologin	
---------------------------------或者
        [root@localhost ~]# awk -F: '/^(root|ftp)/ {print $NF}' /etc/passwd
        /bin/bash
        /sbin/nologin

3、awk的工作原理

1.awk一行一行读取 处理文件,用$0来接收,换行符是分别行的符号 ,
	awk -F: '{print $0}' /etc passwd
	没行读取玩都放在$0里面,然后输出,等同于打印全部
	
2.刚才读入的行,看是否通过F 或者FS 指定分隔符,如果没指定,则使用默认分隔符'空格'来分割成若干字段或(域)
3.print 函数打印 , 里面如果想输出第一列 ,第三列 中间加个','号,这个和awk内置变量OFS一样, OFS默认为空格,于是输出 第一列和第三列中间有个空格 ,如不加逗号则输出第一列和第三列紧挨着
4.输出之后 在从文件获取下一行赋值给$0 重复2步骤分割字段,重复3 步骤执行处理规则,一直重复 直到最后一行

4、awk中的变量

$0			:当前行内容
NR			:行号 
NF			:列数,字段
FS			:输入字段分隔符 默认空格 等同于-F
OFS			:输出字段分隔符,默认空格 和逗号相等,



案例:
		
	案例1:输出/etc/passwd中的所有内容包括行号。
        [root@localhost ~]# awk -F: '{print NR,$0}' /etc/passwd
        1 root:x:0:0:root:/root:/bin/bash
        2 bin:x:1:1:bin:/bin:/sbin/nologin
        3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
        4 adm:x:3:4:adm:/var/adm:/sbin/nologin
        5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        6 sync:x:5:0:sync:/sbin:/bin/sync
	案例2:要求把第7行之后的内容输出出来,包括行号。
        [root@localhost ~]# awk -F: 'NR>7 {print NR,$0}' /etc/passwd
        8 halt:x:7:0:halt:/sbin:/sbin/halt
        9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
        10 operator:x:11:0:operator:/root:/sbin/nologin
        11 games:x:12:100:games:/usr/games:/sbin/nologin
	案例3:要求输出第7行之后的内容且第14行之前的内容输出出来,包含行号
        [root@localhost ~]# awk -F: 'NR>7 && NR<14 {print NR,$0}' /etc/passwd
        8 halt:x:7:0:halt:/sbin:/sbin/halt
        9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
        10 operator:x:11:0:operator:/root:/sbin/nologin
        11 games:x:12:100:games:/usr/games:/sbin/nologin
        12 ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
        13 nobody:x:99:99:Nobody:/:/sbin/nologin
	案例4:由案例3,要求输出每行的UID增加1
        [root@localhost ~]# awk -F: 'NR>7 && NR<14 {print $3,$3+1}' /etc/passwd
        7 8
        8 9
        11 12
        12 13
        14 15
        99 100
	案例5:要求输出倒数第3列
		[root@localhost ~]# awk -F: '{print $(NF-2)}' /etc/passwd
        root
        bin
        daemon
        adm
	案例6:要求不使用-F参数,以:分割,并输出第3列和第5列
        [root@localhost ~]# awk  'BEGIN{FS=":"} {print $3,$5}' /etc/passwd
        0 root
        1 bin
        2 daemon
        3 adm
	案例7:要求实验证明-F 和 FS的优先级	
		证明FS优先级高于-F
        [root@localhost ~]# awk -F: 'BEGIN{FS="/"} {print $3,$1}' /etc/passwd
        bin root:x:0:0:root:
        sbin bin:x:1:1:bin:
        sbin daemon:x:2:2:daemon:	
	案例8:要求以:分割,并输出第3列和第5列,第三列和第五列之间使用+号分割
        [root@localhost ~]# awk -F: 'BEGIN{OFS="+"} {print $3,$5}' /etc/passwd
        0+root
        1+bin
        2+daemon
        3+adm
        4+lp
        5+sync
        6+shutdown
	案例9:取出/etc/passwd文件中以“:”为分隔符,第三列(用户UID)以0结尾的用户?
		[root@localhost tmp]# awk -F: '$3~/0$/ {print $0}' /etc/passwd
	root:x:0:0:root:/root:/bin/bash
	test:x:1000:1000::/home/test:/bin/bash
	~代表模糊匹配 包含什么什么
	0$ 以什么什么(0)结束		

5、格式化输出

printf 
%s 字符类型
%d 数值类型整数
-左对齐  默认右对齐 占15空格   %-d   %-4d    不管有没有都占四个字符
printf不会在行尾自动换行 ,要记得加\n



案例1:要求输出第1列和最后一列,排版整齐
[root@localhost ~]# awk -F: 'BEGIN{OFS=" "} {printf "第一列:%-15s,最后一列:%s \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 

6、操作模式

正则模式awk -F: ‘/正则表达式/’ /etc/passwd
比较模式 awk -F: ‘NR>7’ /etc/passwd > < 输出其行之后
条件模式 awk -F: ‘NR>7’ /etc/passwd
算数运算 awk -F: ‘{print $3,$3+1}’ /etc/passwd
范围模式 awk -F: ‘/root/ ,/ftp/’ /etc/passwd 输出root到ftp的行

7、流程控制

if 
单分支 if(){}
双分支 if() {} else {} 
多分支 if () {} else if() {} else {}


案例:
			
	案例1:打印奇数行的数据
        [root@localhost ~]# awk -F: '{if( NR % 2){print NR,$0}}' /etc/passwd
        1 root:x:0:0:root:/root:/bin/bash
        3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
        5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
        7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
        9 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin		
					
	案例2:打印偶数行的数据
        [root@localhost ~]# awk -F: '{if( NR % 2==0){print NR,$0}}' /etc/passwd
        2 bin:x:1:1:bin:/bin:/sbin/nologin
        4 adm:x:3:4:adm:/var/adm:/sbin/nologin
        6 sync:x:5:0:sync:/sbin:/bin/sync
        8 halt:x:7:0:halt:/sbin:/sbin/halt
        10 operator:x:11:0:operator:/root:/sbin/nologin
		
		注:单分支情况下是可以省略if,多分支情况下不能省略
				
	案例3:要求打印出偶数行中的包含bash的行
		[root@localhost ~]# awk -F: '{if( NR % 2==0){print NR,$0}}' /etc/passwd | awk -F: '/bash/' 
            24 test:x:996:995::/home/test:/bin/bash
            26 test111:x:1001:1001::/home/test111:/bin/bash
      ------------------------------------------------------------------------
		[root@localhost ~]# awk -F: '/bash/{if(NR % 2 ==0) {print NR,$0}}' /etc/passwd
            24 test:x:996:995::/home/test:/bin/bash
            26 test111:x:1001:1001::/home/test111:/bin/bash

	案例4:要求在奇数行前输出奇数,偶数行前输出偶数
		[root@localhost ~]# awk -F: '{if (NR %2) {printf "奇数:%s \n", $0} else {printf "偶数:%s \n", $0}}' /etc/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 
        奇数:lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin 
        偶数:sync:x:5:0:sync:/sbin:/bin/sync 
        奇数:shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 
        偶数:halt:x:7:0:halt:/sbin:/sbin/halt 
        奇数:mail:x:8:12:mail:/var/spool/mail:/sbin/nologin 
        偶数:operator:x:11:0:operator:/root:/sbin/nologin 
        奇数:games:x:12:100:games:/usr/games:/sbin/nologin 		

	案例5:在前7行前加7, 前14行前加14,其他原样输出

        [root@localhost ~]# awk -F: '{if(NR<=7 ) {printf  "7 %s\n", $0}else if (NR<=14) {printf "14 %s\n",$0}else {print NR, $0}}' /etc/passwd




for
for (变量 in 数组) {语句}
for (变量;条件;表达式){语句}

案例:
			
	案例1:将/etc/nginx/nginx.conf中的所有的词的个数
		[root@localhost ~]# egrep -o  "[0-9A-Za-z]+" /etc/nginx/nginx.conf | awk '{arr[$1]++} END{for(i in arr){printf "%-20s %d\n",i,arr[i]}}'   		
				
	案例2:要求统计以#开头的行中包含的词的个数
		[root@localhost ~]# egrep "^ *#" /etc/fstab | egrep -o  "[0-9A-Za-z]+"  | awk '{arr[$1]++} END{for(i in arr){printf "%-20s %d\n",i,arr[i]}}' 		

	案例3:输入一个文件路径,要求打印出它的数字权限(不允许使用stat)
		[root@localhost ~]# ll [路径] | awk 'BEGIN{FS=""}{if($2=="r"){u=u+4} if($3=="w"){u=u+2} if($4=="x"){u=u+1} if($5=="r"){g=g+4} if($6=="w"){g=g+2} if($7=="x"){g=g+1} if($8=="r"){o=o+4} if($9=="w"){o=o+2} if($10=="x"){o=o+1}}END{print u,g,o}'




		
		
		

				
					

		
		
		
					
posted @ 2021-10-10 13:16  迪迦张  阅读(26)  评论(0编辑  收藏  举报