28-Linux-AWK使用范例

awk使用范例

  •   原文件内容:
      [root@CentOS8 data]# cat emp.txt 
      
      Beth:4.00:0
      Dan:3.75:0
      kathy:4.00:10
      Mark:5.00:20
      Mary:5.50:22
      Susie:4.25:18
    
  •   以 :为分隔符搜索 emp.txt 文件中每行的 1,3字段,且打印至终端时在其中间以 tab键为字段分隔符来显示
      
      [root@CentOS8 data]# awk -F":" '{print $1"\t"$3}' emp.txt 
      Beth	0
      Dan	0
      kathy	10
      Mark	20
      Mary	22
      Susie	18
    
  •   与-F作用相同的写法 -v FS=
      
      [root@CentOS8 data]# awk -v FS=":" '{print $1"\t"$3}' emp.txt 
      Beth	0
      Dan	0
      kathy	10
      Mark	20
      Mary	22
      Susie	18
    
  •   指定 tab键 为字段分隔符显示 emp.txt 文件的1,3字段 OFS
      
      [root@CentOS8 data]# awk -v OFS="\t" -F":" '{print $1,$3}' emp.txt 
      Beth	0
      Dan	0
      kathy	10
      Mark	20
      Mary	22
      Susie	18
    
  •   同样也可以这样写:应注意有两个 -v
      
      [root@CentOS8 data]# awk -v FS=':' -v OFS='\t' '{print $1,$3}' emp.txt 
      Beth	0
      Dan	0
      kathy	10
      Mark	20
      Mary	22
      Susie	18
    
  •   另外,还可以输入记录分隔符,指定输入时的换行符
      
      例如:以 ;为记录分隔符,只要遇到 ;就将 ;换成\n换行
      
      应注意原文件每行结尾都有一个隐藏的\n换行符,输出结果仍将\n换行符视为某行的一部分
      
      [root@CentOS8 data]# cat file.txt
      student;liming
      tech;wang;ma
      
      [root@CentOS8 data]# awk -v RS=';' '{print}' file.txt 
      student
      liming
      tech
      wang
      ma
    
  •   那么如何证明这一点呢?
      
      输出行号一共为4行
      
      [root@CentOS8 data]# awk -v RS=';' '{print NR}' file.txt 
      1
      2
      3
      4
      
      而之前的输出字符似乎是五行 :
      
      [root@CentOS8 data]# awk -v RS=';' '{print}' file.txt 
      student
      liming
      tech
      wang
      ma
      
      结论证明:NR为显示行号,$0是显示每一行;意思是输出每一行并为其添加行号
      
      [root@CentOS8 data]# awk -v RS=';' '{print $0,NR}'le.txt 
      student 1
      liming
      tech 2
      wang 3
      ma
       4
      
      所以第一行的liming \n tech三者被视为同一新行,此外,ma后面依旧有一个隐藏的\n换行符
    
  •   使用ORS输出记录分隔符,输出时用指定符号代替换行符  只要遇到 ;就将其替换成@@@输出
      
      若RS不指定,默认将行尾隐藏的\n换行符替换
      
      [root@CentOS8 data]# awk -v RS=';' -v ORS='@@@'  '{print $0}' file.txt
      student@@@liming
      tech@@@wang@@@ma
      @@@
    
  •   还可以使用NF来显示每一行的字段个数
      
      [root@CentOS8 data]# awk -v RS=';' '{print NF}' file.txt 
      1
      2
      1
      1
    
  •   当然,如果不添加额外的选项,仅显示原文件的话,此时只有两行,如果该行中没有空格分隔字段,那么该行会被视为一个整体 即:一个字段
      
      [root@CentOS8 data]# awk '{print NF}' file.txt 
      1
      1
    
  •   取出磁盘最大使用率
      
      [root@CentOS8 data]# df -h|grep 'dev/sd'|awk -F% '{print $1}'|awk '{print $5}'|sort -n|tail -1
      13
    
  •   另一种写法
      
      [root@CentOS8 data]# df -h|awk -F" +|%" '$0 ~ /^\/dev\/sd/{print $5}'|sort -n|tail -1
      13
    
	-F	指明输入时选定的字段分隔符
	
    -v	Var=value
		     变量赋值
	
    FS	输入字段分隔符,默认为空格
	
    OFS	输出字段分隔符,默认为空格
	
    RS	输入记录分隔符,指定输入时的换行符
	
    ORS	输出记录分隔符,输出时用指定符号代替换行符 
	
    NF	显示字段数量
	
    NR	记录每行行号
  •   除了处理一个文件,是不是可以处理多个文件呢?
    
      同时分别显示两个文件的行号
    
      [root@CentOS8 data]# cat file.txt 
      student;liming
      tech;wang;ma
      
      [root@CentOS8 data]# cat emp.txt 
      Beth:90:one
      Dan:110:two
    
      [root@CentOS8 data]# awk '{print FNR}' file.txt emp.txt 
      1
      2
      1
      2
      
      [root@CentOS8 data]# awk '{print $0,FNR}' file.txt emp.txt 
      student;liming 1
      tech;wang;ma 2
      Beth:90:one 1
      Dan:110:two 2
    
  •   另外还有其他有意思的选项
    
      有关NR、NF变量的使用
      在以前我们曾尝试用各种基础命令来取出IP地址、磁盘利用率、软件版本类型等等如此之类的需求;而awk可以非常便捷的做到 :
    
      取出磁盘利用率最大的分区
    
      [root@CentOS8 data]# df -h|awk -F" +|%" '$0~"/dev/sda"{print $5}'|sort -n|tail -1
      13
    
  •   取出用户的家目录
    
      [root@CentOS8 data]# awk -F: '{print $(NF-1)}' /etc/passwd
      /root
      /bin
      ………….
      /home/td
      /home/mage
    
  •   取出主机ip
    
      [root@CentOS8 data]# ifconfig ens33|awk NR==2'{print $NR}'
      192.168.124.3
    
  •   有关FILENAME的使用
      文件内容全部替换成文件名,即输出文件个数=文件行数
    
      [root@CentOS8 data]# awk '{print FILENAME}'  file.txt 
      file.txt 
      file.txt
      
      [root@CentOS8 data]# awk '{print FILENAME}'  emp.txt 
      emp.txt
      emp.txt
    
      [root@CentOS8 data]# awk '{print FNR,FILENAME}'  emp.txt file.txt 
      1 emp.txt
      2 emp.txt
      1 file.txt
      2 file.txt
    
  •   ?awk还可以加减乘除?
    
      [root@CentOS8 data]# awk 'BEGIN{print 3*5}'
      15
      
      [root@CentOS8 data]# awk 'BEGIN{print (2*5-6)/2^2}'
      1
    
  •   显示命令行参数的个数
    
      [root@CentOS8 data]# awk 'BEGIN{print ARGC}' 
      1
      
      [root@CentOS8 data]# awk 'BEGIN{print ARGC}' emp.txt 
      2
      
      [root@CentOS8 data]# awk 'BEGIN{print ARGC}' emp.txt file.txt 
      3
      
      [root@CentOS8 data]# awk 'BEGIN{print ARGC}' emp.txt file.txt pig.txt 
      4
    
  •   ARGV:数组
    
      [root@CentOS8 data]# awk 'BEGIN{print ARGV[0]}' emp.txt file.txt pig.txt 
      awk
      
      [root@CentOS8 data]# awk 'BEGIN{print ARGV[1]}' emp.txt file.txt pig.txt 
      emp.txt
      
      [root@CentOS8 data]# awk 'BEGIN{print ARGV[2]}' emp.txt file.txt pig.txt 
      file.txt
      
      [root@CentOS8 data]# awk 'BEGIN{print ARGV[3]}' emp.txt file.txt pig.txt 
      pig.txt
    
  •   FNR	分别记录多个文件行号
      FILENAME	当前文件名
      ARGC	终端输入时命令行参数的个数
             BEGIN	加减乘除等运算
      ARGV	数组,命令行的各个参数
    
  •   除了可以使用awk的内置变量,还可以自定义变量
    
      [root@CentOS8 data]# awk -F: -v user="username : " '{print user$1}' /etc/passwd
      username : root
      username : bin
      username : daemon
      username : adm
      ……………………………
    
  •   自定义多个变量
    
      [root@CentOS8 data]# awk -F: -v user="username : " -v usid="useruid : " -v ugid= :" usergid  " '{print user$1"\t"usid$3"\t"ugid$4}' /etc/passwd
      username : root	useruid : 0	 usergid :0
      username : bin	useruid : 1	 usergid  :1
      username : daemon	useruid : 2	 usergid  :2
      username : adm	useruid : 3	 usergid  :4
      ……………………………………
    
  •   也可以将变量定义在program中
    
      [root@CentOS8 data]# awk -F: '{user="username : ";usid="useruid : ";ugid=" usergid :";print user$1"\t"usid$3"\t"ugid$4}' /etc/passwd
      username : root	useruid : 0	 usergid :0
      username : bin	useruid : 1	 usergid :1
      username : daemon	useruid : 2	 usergid :2
      username : adm	useruid : 3	 usergid :4
      ………………………………………………
    
  •   倘若你已经在shell中定义过要使用的变量,同样在awk中你也可以调用它
    
      [root@CentOS8 data]# user="username:" uuid="useruid:" ugid="usergid:";awk -F: -v i=$user -v u=$uuid -v g=$ugid '{print i$1"\t"u$3"\t"g$4}' /etc/passwd
      username:root	useruid:0	usergid:0
      username:bin	useruid:1	usergid:1
      username:daemon	useruid:2	usergid:2
      username:adm	useruid:3	usergid:4
      …………………………………………
    
  •   将执行的命令放在一个文件中,使用awk调用该文件一样OK
    
      [root@CentOS8 data]# vim awk.txt
      
      [root@CentOS8 data]# cat awk.txt 
      {user="username : ";usid="useruid : ";ugid=" usergid  ";print user$1"\t"usid$3"\t"ugid$4}
    
      [root@CentOS8 data]# awk -F: -f awk.txt /etc/passwd
      username : root	useruid : 0	 usergid  0
      username : bin	useruid : 1	 usergid  1
      username : daemon	useruid : 2	 usergid  2
      username : adm	useruid : 3	 usergid  4
      ………………………………
    

printf命令

格式化输出:printf “FORMAT”,item1,item2,….
	必须指定FORMAT
	不主动换行,需手动给出\n换行符
	FORMAT中需要分别为后面每个item指定格式符
格式符:与item相呼应
	%c:显示字符的ASCII码(不常用)
	%d,%i:显示十进制整数(常用)
	%e,%E:显示科学计数法数值
	%f:显示为浮点数(小数位)
	%g,%G:以科学计数法或浮点形式显示数值(也许你需要将小数精确至0.001什么的)%s:显示字符串%u:无符号整数%%:显示%自身
修饰符:
	#[.#]	第一个数字控制显示的宽度;第二个#表示小数点后精度 %3.1f
	    -	左对齐(默认为右对齐)%-15s
	   +	显示数值的正负号 %+d
  •   默认向右对其显示
    
      [root@CentOS8 data]# cat emp.txt 
      Beth:-90:233:-12:seur:out
      Dan:110:-7:66:root
      
      [root@CentOS8 data]# awk -F: '{printf "%4s %10d %5d\n",$1,$3,$4}' emp.txt
      Beth        233   -12
       Dan        -7    66
    
  •   加-左对齐
    
      [root@CentOS8 data]# awk -F: '{printf "%-4s     %-10d %d\n",$1,$3,$4}' emp.txt
      Beth     233        -12
      Dan     -7        66
    
  •   显示’数值‘的正负
    
      [root@CentOS8 data]# awk -F: '{printf "%-5s  %5+d %5+d\n",$1,$3,$4}' emp.txt 
      Beth    +233   -12
      Dan       -7   +66
    
  •   之前操作的示例中有计算加减乘除的展示
      那么,awk中的算术操作符以及其他的操作符有哪些:
    
x+y	加法
x-y	减法
x*y	乘法
x/y	除法
x^y	幂运算(指数)
x%y	取模(除余)
-x	转换成负数
+x	将字符串转换为数值

赋值操作符:

=	右边赋值给左边
+=	先加,再赋值
-=	先减,再赋值
*=	先乘,再赋值
/=	先除,再赋值
%=	先取模,再赋值
^=	先幂运算,再赋值
++	递增操作
--	递减操作

比较操作符:

==	判断相等
!=	判断不等
\>	判断大于
\>=	判断大于等于
<	判断小于
<=	判断小于等于

模式匹配符:

~	左边是否和右边匹配包含
!~	是否不匹配

逻辑操作符:

&&	逻辑与
||	逻辑或
!	逻辑非
  •   比较下列两个命令语句有何区别
    
      [root@CentOS8 data]# awk 'BEGIN{i=0;print ++i,i}'
      [root@CentOS8 data]# awk 'BEGIN{i=0;print i++,i}'
    
  •   第一个是先加,之后将加得的数和i打印
      第二个是先打印i的值,再将i加得的数打印
    
      [root@CentOS8 data]# awk 'BEGIN{i=0;print ++i,i}'
      1 1
      [root@CentOS8 data]# awk 'BEGIN{i=0;print i++,i}'
      0 1
    
  •   awk中的PATTERN模式
    
PATTERN:根据pattern条件,过滤匹配的行;然后再做处理
	1:若pattern未指定:视为空模式,匹配所有行
	2:/relational expression/:仅处理能够被模式匹配到的行,且需要用//扩入
	3:relational expression:关系表达式,仅结果为真,才会进行处理
	真:结果为非0值,非空字符串都为真
	假:结果为空字符串或0值都为
	4:line ranges:行范围
	startine,endline:/pat1/,/pat2/不支持直接给出数字格式。
	5:BEGIN/END模式
	BEGIN{}:仅在开始处理文件中的文本之前执行一次
	END{}:仅在文本处理完成之后执行一次。
  •   匹配/etc/passwd 中所有行的第N个字段所在的那行包含root的
    
      [root@CentOS8 data]# awk  -F: '$0 ~ /root/{print $1}'  /etc/passwd
      root
      operator
    
  •   当然,如果匹配一个不存在的字符串是没有反应的
    
      [root@CentOS8 data]# awk  -F: '$0 ~ /kxxxla/{print $1}'  /etc/passwd
    
      [root@CentOS8 data]# awk  -F: '$0 ~ /root/{print $3}'  /etc/passwd
      0
      11
      
      [root@CentOS8 data]# awk  -F: '$0 ~ /root/{print $5}'  /etc/passwd
      root
      operator
    
  •   查看/etc/passwd文件便可清楚了解
    
      [root@CentOS8 data]# cat /etc/passwd
      root:x:0:0:root:/root:/bin/bash
      ………………………………….
      operator:x:11:0:operator:/root:/sbin/nologin
    
  •   匹配/etc/passwd 中所有行的第N个字段所在的那行为0的
    
      [root@CentOS8 data]# awk -F: '$4==0' /etc/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
      operator:x:11:0:operator:/root:/sbin/nologin
    
      [root@CentOS8 data]# awk -F: '$3==0' /etc/passwd
      root:x:0:0:root:/root:/bin/bash
    
  •   于此之外,使用!~可以匹配相反的效果
    
      [root@CentOS8 data]# awk -F: '!$4==0' /etc/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
    
  •   匹配/etc/passwd 中所有行的第N个字段所在的那行为非0的
    
      [root@CentOS8 data]# awk -F: '!$4==0' /etc/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
      …………………………………..过多不做演示
    
  •   匹配/etc/passwd 中所有行的第N个字段所在的那行不包含root的
    
      [root@CentOS8 data]# awkawk  -F: '$0 !~ /root/{print $5}' tc/passwd
      bin
      daemon
      adm
      ………..过多不做演示
    
  •   有关逻辑与或非的示例:
      匹配/etc/passwd中所有行的第三字段数值在0-5之间的,打印符合条件的行的第一字段
    
      [root@CentOS8 data]# awk -F: '$3>=0 && $3<=5 {print $1}' /etc/passwd|tr '\n' ' '
      root bin daemon adm lp sync 
    
  •   匹配/etc/passwd中所有行的第三字段的数值在小于等于0或大于等于1000之间的,打印符合条件的行的第一字段
    
      [root@CentOS8 data]# awk -F: '$3<=0 || $3>=1000 {print $1}' /etc/passwd
      root
      nobody
      td
    
  •   匹配/etc/passwd中所有行的第三字段数值在小于1000的,取反变为大于等于1000的,打印符合条件的行的第一字段
    
      [root@CentOS8 data]# awk -F: '!($3<1000) {print $1}' /etc/passwd
      nobody
      td
    
  •   有关PATTERN模式的示例:
    
      原文件:
    
[root@CentOS8 data]# cat /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Wed Sep 25 20:03:53 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
UUID=e2e0f44d-0ae9-4159-a99f-6a1c72dcccbe /                       xfs     defaults        0 0
UUID=deb9638d-76ba-4370-90f1-962cd4ab55b5 /boot                   ext4    defaults        1 2
UUID=40aac826-ee18-4927-8574-c8618c4ea1e7 /data                   xfs     defaults        0 0
UUID=d12cdea2-cb68-4aa7-97cd-9002297faf05 swap                    swap    defaults        0 0
  •   仅匹显示以UUID开头的行
    
      [root@CentOS8 data]# awk '/^UUID/{print $1}' /etc/fstab 
      UUID=e2e0f44d-0ae9-4159-a99f-6a1c72dcccbe
      UUID=deb9638d-76ba-4370-90f1-962cd4ab55b5
      UUID=40aac826-ee18-4927-8574-c8618c4ea1e7
      UUID=d12cdea2-cb68-4aa7-97cd-9002297faf05
    
  •   取反
    
[root@CentOS8 data]# awk '!/^UUID/{print $0}' /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Wed Sep 25 20:03:53 2019
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
# After editing this file, run 'systemctl daemon-reload' to update systemd
# units generated from this file.
#
  •   Relational expression:关系表达式
    
      [root@CentOS8 data]# awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
      root /bin/bash
      td /bin/bash
      mage /bin/bash
    
发布了63 篇原创文章 · 获赞 102 · 访问量 3569

猜你喜欢

转载自blog.csdn.net/dushansao/article/details/102947242