ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

day16 Linux三剑客之awk

2021-10-09 20:00:28  阅读:131  来源: 互联网

标签:passwd etc day16 awk print root localhost 三剑客


day16 Linux三剑客之awk

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

什么是awk,主要作用是什么?
	awk 主要用来处理文件,将文本按照指定的格式输出。其中包含变量,循环以及数组。

2、awk的格式

awk的格式:
    awk [选项] '匹配规则和处理规则' [处理文本路径]
        [root@localhost ~]# awk -F: '{print $1}' /etc/passwd		 # 打印第一行

    标准输出 | awk [选项] '匹配规则和处理规则' 
        [root@localhost ~]# cat /etc/passwd | awk -F: '{print $1}'    # 打印第一行

常用命令选项:
    -F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
    -v var=value   赋值一个用户定义变量,将外部变量传递给awk
    -f scripfile  从脚本文件中读取awk命令
    -m[fr] val   对val值设置内在限制,-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

    匹配规则主要是正则表达式
        处理规则就有很多了:
        设置变量
        设置数组
        数组循环
        加减乘数运算
        字符串拼接

    匹配规则:
        1、字符串
        2、正则表达式

    处理规则:
        BEGIN{}		: BEGIN是在awk处理文本之前运行 # 注:所有的变量的定义都应该放在BEGIN里面
        //			: 使用的匹配规则
        {}			:循环(每次只处理一行数据)
        END{}		:当所有的处理全部执行完毕之后,执行END中的相关操作
        
案例1:把/etc/passwd中的包含root的行打印出来
    [root@localhost ~]# awk -F: '/root/' /etc/passwd
    
案例2:把/etc/passwd中以root开头的行打印出来
    [root@localhost ~]# awk -F: '/^root/' /etc/passwd
    
案例3:将/etc/passwd中匹配第三列和第五列的数据
	[root@localhost ~]# awk -F: '{print $3,$5}' /etc/passwd
	
案例4:打印以root或者ntp开头的行的解析器
	[root@localhost ~]# awk -F: '/^(root|ntp)/{print $7}' /etc/passwd

3、awk的工作原理

    (1)awk会接收一行作为输入,并将这一行赋给awk的内部变量$0,每一行也可称为一个记录,行的边界是以换行符作为结束(表明:awk是一行一行的去处理文本的)
    
    (2)然后,刚刚读入的行被以:为分隔符分解成若干字段(或域),每个字段存储在已编号的变量中,编号从$1开始,最多达100个字段
    # 注意:如果未指定行分隔符,awk将使用内置变量FS的值作为默认的行分隔符,FS默认值为空格,如果说要指定分隔符,需要使用-F参数或者重新定义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)的步骤
    该过程一直持续到所有行处理完毕

4、awk中的变量

awk中的变量:
    $0: 保存当前行的内容          # 打出所有
    NR: 记录号(行号),每处理完一条记录,NR值加1  # 行号
    NF: 保存记录的字段数,$1,$2...$100  
    FS: 输入字段分隔符,默认空格   # 'BEGIN{FS=":"}
    OFS:输出字段分隔符            # 'BEGIN{OFS="+"}{print $3,$7}'
    
案例1:输出/etc/passwd中的所有内容包括行号。
	[root@localhost ~]# awk -F: '{print NR,$0}' /etc/passwd
	
案例2:要求把第7行之后的内容输出出来,包括行号。
	[root@localhost ~]# awk -F: 'NR>7 {print NR,$0}' /etc/passwd     # 可以用条件来完成,NR代表行号
	
案例3:要求输出第7行之后的内容且第14行之前的内容输出出来,包含行号
	[root@localhost ~]# awk -F: 'NR>7 && NR<14 {print NR,$0}' /etc/passwd
	
案例4:由案例3,要求输出每行的UID增加1
	[root@localhost ~]# awk -F: 'NR>7 && NR<14 {print $3,$3+1}' /etc/passwd
	
案例5:要求输出倒数第3列
	[root@localhost ~]# awk -F: '{print $(NF-2)}' /etc/passwd   # 在这里NF代表最后一列
	
案例6:要求不使用-F参数,以:分割,并输出第3列和第5列
	[root@localhost ~]# awk 'BEGIN{FS=":"}{print $3,$5}' /etc/passwd
	
案例7:要求实验证明-F 和 FS的优先级
	[root@localhost ~]# awk -F/ 'BEGIN{FS=":"}{print $3,$5}' /etc/passwd   # FS优先级>-F
	
案例8:要求以:分割,并输出第3列和第7列,第三列和第五列之间使用+号分割
	[root@localhost ~]# awk -F: 'BEGIN{OFS="+"}{print $3,$7}' /etc/passwd 

5、格式化输出

格式化输出
	printf格式:
        awk -F: '{printf "用户名:%s 用户id:%s\n",$1,$3}' /etc/passwd
        awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd    
		%s 字符类型
		%d 数值类型
		占15格的字符串
		- 表示左对齐,默认是右对齐
		printf默认不会在行尾自动换行,加\n
		[root@localhost ~]# awk -F: 'BEGIN{OFS=" "}{printf "%-4d %s\n", $3,$7}' /etc/passwd
		
案例1:要求输出第1列和最后一列,排版整齐
	第一种方法:
		[root@localhost ~]# awk -F: '{printf "%-15s %s\n",$1,$NF}' /etc/passwd
		
	第二种方法:适用于字符特别长的
		[root@localhost ~]# awk -F: '{print length($1)}' /etc/passwd   # 得到最长字符的个数
		[root@localhost ~]# awk -F: '{printf "%-15s %s\n",$1,$NF}' /etc/passwd

6、操作模式

1)、正则模式
	[root@localhost ~]#awk -F: '/^root/' /etc/passwd    # //包含

2)、比较模式
    > < 
    [root@localhost ~]# awk -F 'NR > 7' /etc/passwd       # 比较>

3)、条件模式
	[root@localhost ~]# awk -F: 'NR>7 && NR<14 {print NR,$0}' /etc/passwd  # 达成条件执行

4)、算数运算
	[root@localhost ~]# awk -F '{print $3,$3+1}' /etc/passwd    # 给uid加1

5)、范围模式
    [root@localhost ~]# awk -F: '/root/,/ftp/{print $1}' /etc/passwd    # root到ftp的范围

7、流程控制

if

if判断:
    单分支
    if () {}

    双分支
    if () {} else {}

    多分支
    if(){} else if() {} else{}
    
    案例1:打印奇数行的数据
        [root@localhost ~]# awk -F: '{if(NR%2){print NR,$0}}' /etc/passwd
        
	案例2:打印偶数行的数据
		[root@localhost ~]# awk -F: '{if(NR%2==0){print NR,$0}}' /etc/passwd
		[root@localhost ~]# awk -F: 'NR%2==0{print $0}' /etc/passwd   # 单分支不加if也可以
		注:单分支情况下是可以省略if,多分支情况下不能省略
		
	案例3:要求打印出偶数行中的包含bash的行
		[root@localhost ~]# awk -F: '/bash/{if(NR%2==0){print NR,$0}}' /etc/passwd
		
	案例4:要求在奇数行前输出奇数,偶数行前输出偶数
		[root@localhost ~]# awk -F: '{if(NR%2){printf "奇数行:%s\n",$0}else{printf "偶数行:%s\n",$0}}' /etc/passwd
		
	案例5:在前7行前加7, 前14行前加14,其他原样输出
		[root@localhost ~]# awk -F: '{if(NR<=7){printf "7 %s\n",$0,NR}else if(NR<=14){printf "14 %s\n",$0}else{print $0}}' /etc/passwd

for循环

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

    知识储备:
        ++ : 每次加1
        -- : 每次减1
    
    案例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 "%-15s %d\n", i,arr[i]}}'
    	
	案例2:要求统计以#开头的行中包含的词的格式
		[root@localhost ~]# egrep '^ *#' /etc/fstab | egrep -o '[0-9a-zA-Z]+' /etc/nginx/nginx.conf | awk '{arr[$1]++}END{for (i in arr){printf "%-15s %d\n", i,arr[i]}}'
		
	案例3:输入一个文件路径,要求打印出它的数字权限(不允许使用stat)
		[root@localhost ~]# ll /etc/fstab | awk 'BEGIN{FS=""}{if($2=="r"){u+=4} if($3=="w"){u+=2} if($4=="x"){u+=1} if($5=="r"){g+=4} if($6=="w"){g+=2} if($7=="x"){g+=1} if($8=="r"){o+=4} if($9=="w"){o+=2} if($10=="x"){o+=1}}END{print u,g,o}'

标签:passwd,etc,day16,awk,print,root,localhost,三剑客
来源: https://www.cnblogs.com/1069943893com/p/15387396.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有