awk - pattern scanning and processing language

基本用法:gawk [option] 'program' FILE ... program: PATTERN{ACTION STATEMENTS} 语句之间用分号分隔 print,printf 选项: -F: 指明输入时用到的分隔符: -v var=value 自定义变量:

1、 print

	 print item1, item2, ...
	 要点:
		(1)逗号分隔符:
		(2)输出的各item可以字符串,也可以是数值:当前记录的字段、变量或awk的表达式:
		(3)如省略item,相当于print $0
2、 变量
	2.1 内建变量
		FS:  输入字段分隔符, 默认为空白字符
		OFS: 输出字段分隔符, 默认为空白字符
		RS:  输入时的换行符
		ORS: 输出时的换行符
		
		NF:  字段数量
			 {print NF}   {print $NF}
		NR:  行数
		FNR: 各文件分别计数: 行数:
		
		FILENAME: 当前文件名:
		
		ARGC: 命令行参数的个数:
		ARGV: 数组,保存的是命令行所给定的各参数:
		
	2.2 自定义变量
	    (1)-v var=value 
			
			变量名区分字符大小写:
		
		(2)在program中直接定义

3、printf命令

	格式化输出:printf FORMAT, item1, item2, ...
	
	   (1)FORMAT必须给出;
	   (2)不会自动换行,需要显示给出换行控制符, \n
	   (3)FORMAT 中需要分别为后面的每一个item指定一个格式化符号:
        	     
		格式符:
			%c 显示字符的ASCII码
			%d  %i 显示十进制整数
			%e  %E 科学计数法数值显示
			%f 显示为浮点数
			%g  %G 以科学计数法或浮点形式显示数值
			%s  显示字符串
			%u  无符号整数
			%%  显示%自身
			
		修饰符:
			#[.#]  第一个数字控制显示的宽度: 第二个#表示小数点后的精度:
				%3.1f
			   -   左对齐
			   +   显示数值的符号
4、操作符
    
	算术操作符:
		x+y, x-y, x*y, x/y, X^y, x%y
		-x
		+x: 转换为数值:
	
	字符串操作符: 没有符号的操作符,字符串连接
	
	赋值操作符:
		=, +=, -=,*=, /=, %=, ^=
		++, --
	
	比较操作符:
		>, >=, <, <=, !=, ==
	
	模式匹配符:
		~  左边是否匹配右边
		!~  左边是否不匹配右边
	
	逻辑操作符:
		&&
		||
		!
	
	函数调用:
		function_name(argu1, argu2, ...)
		
	条件表达式:
		selector?if-true-expression:if-false-expression

[root@centos7 ~]#awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%s\n",$1,usertype}' /etc/passwd root:Sysadmin or SysUser bin:Sysadmin or SysUser daemon:Sysadmin or SysUser adm:Sysadmin or SysUser lp:Sysadmin or SysUser sync:Sysadmin or SysUser shutdown:Sysadmin or SysUser halt:Sysadmin or SysUser mail:Sysadmin or SysUser operator:Sysadmin or SysUser games:Sysadmin or SysUser ftp:Sysadmin or SysUser nobody:Sysadmin or SysUser pegasus:Sysadmin or SysUser systemd-network:Sysadmin or SysUser

5、PATTERN

	(1)empty: 空模式,匹配每一行:
	(2)/regular expression/: 仅处理能够被此处的模式匹配到的行:
	
 [root@centos7 ~]#awk '/^UUID/{print $1}' /etc/fstab  
      UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f
      UUID=6e6694fc-5a2f-47a1-b96b-509621e5fc1e
      UUID=1828df2b-47f3-442d-9681-ca17539861d9
      UUID=111bb92e-4d79-486a-afaf-38ba79856d30
    
      [root@centos7 ~]#awk '!/^UUID/{print $1}' /etc/fstab    // !表示取反
				#
				#
        
	(3)relation expression: 关系表达式: 结果有真有假:结果为真才会被处理:
		真:结果为非0值,非空字符串:
		
		[root@centos7 ~]#awk -F: '$3>=1000{print $1,$3}' /etc/passwd  
        nfsnobody 65534
        xp018970 1000
		
		[root@centos7 ~]#awk -F: '$NF~/bash$/{print $1,$NF}' /etc/passwd  
		root /bin/bash
		xp018970 /bin/bash
	
	(4)line range: 行范围
		startline,endline: /pattern1/,/pattern2/
		
		[root@centos7 ~]#awk -F: '(NR>=3&&NR<=10){print $1}'  /etc/passwd
		daemon
		adm
		lp
		sync
		shutdown
		halt
		mail
		operator
			   
	(5)BEGIN/END模式
		BEGIN{}: 仅在开始(处理文件中的文本)之前执行一次:
		END{}:仅在文本处理完成之后执行一次:

[root@centos7 ~]#awk -F: 'BEGIN{print "Username Uid \n============================"}{printf "%-19s|%d\n", $1,$3}END{print "============================ \n END "}' /etc/passwd

		Username           Uid       
		============================
		root               |0
		bin                |1
		daemon             |2
		adm                |3
		lp                 |4
		sync               |5
		shutdown           |6
		halt               |7
		mail               |8
		operator           |11
		games              |12
		ftp                |14
		nobody             |99
		pegasus            |66
		systemd-network    |192
		dbus               |81
		polkitd            |999
		unbound            |998
		libstoragemgmt     |997
		rpc                |32
		colord             |996
		saslauth           |995
		abrt               |173
		setroubleshoot     |994
		rtkit              |172
		pulse              |171
		rpcuser            |29
		nfsnobody          |65534
		named              |25
		radvd              |75
		qemu               |107
		chrony             |993
		mysql              |27
		tss                |59
		geoclue            |992
		hacluster          |189
		usbmuxd            |113
		cockpit-ws         |991
		gluster            |990
		gdm                |42
		gnome-initial-setup|989
		sshd               |74
		avahi              |70
		postfix            |89
		ntp                |38
		tcpdump            |72
		xp018970           |1000
		dovecot            |97
		dovenull           |988
		============================ 
					END           
		

6、 控制语句

	if(condition){statements}
	if(condition){stations} else {statements}
	while(condition){stations}
	do {statements} while(condition)
	for(expr1;expr2;expr3) {statements}
	break
	continue
	delete array
	exit
	{ statements }
	
	6.1 if-else
	
		语法:if(condition){stations} else {statements}
	     
			[root@centos7 ~]#awk -F: '{if($3>=1000) print $1,$3}' /etc/passwd    
			nfsnobody 65534
			xp018970 1000
		  
			[root@centos7 ~]#awk -F: '{if($3>=1000) {printf "%19s : Common User\n",$1} else {printf "%19s : root or Sysuser\n", $1} }' /etc/passwd    
               root : root or Sysuser
                bin : root or Sysuser
             daemon : root or Sysuser
                adm : root or Sysuser
                 lp : root or Sysuser
               sync : root or Sysuser
			shutdown : root or Sysuser
		   
			[root@centos7 ~]#awk -F: '{if($NF=="/bin/bash") printf "%8s:%s \n", $1,$NF}' /etc/passwd
				root:/bin/bash 
			xp018970:/bin/bash
			
			[root@centos7 ~]#awk '{if(NF>5) print $0}'  /etc/fstab    //默认为空白字符为分隔符,字段数大于5,就打印整行
			
			[root@centos7 ~]#df -h |awk -F '[[:space:]]+|%'  '/^\/dev/ {print $1,$5}' |awk '{if($2>=80) printf "WarningDisk : %s\n", $1}' 
			WarningDisk : /dev/sr0
			
			[root@centos7 ~]#df -h |awk -F '[[:space:]]+|%' '$0 ~ "^/dev" {print $1,$5}' |awk '$2>=80{print $1}'      
			/dev/sr0
		  
		    [root@centos7 ~]#df -h |awk -F"%" '/^\/dev/{print $1}' | awk '{if($NF>=30) printf "warning disk:%s\n", $1}'
			warning disk:/dev/sda3
			warning disk:/dev/sr0
            
			  使用场景:对awk取得的整数行或某个字段做条件判断:
			  
	6.2 while 循环
		语法:while(condition)statement
			条件“真”,进入循环: 条件“假”,退出循环:
			
			使用场景:对一行内的多个字段逐一类似处理时使用:对数组中的各元素逐一处理时使用:
			 
			[root@centos7 ~]#awk  '/^[[:space:]]*linux16/ {i=1;while(i<NF) {print $i,length($i);i++ }}'  /etc/grub2.cfg 
			linux16 7
			/vmlinuz-4.20.3-1.0-xinzhoulinux 32
			root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
			ro 2
			crashkernel=auto 16
			rhgb 4
			quiet 5
			
			[root@centos7 ~]#awk  '/^[[:space:]]*linux16/ {i=1;while(i<NF) {if(length($i)>=7) {print $i,length($i)};i++ }}'  /etc/grub2.cfg 
			linux16 7
			/vmlinuz-4.20.3-1.0-xinzhoulinux 32
			root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
			crashkernel=auto 16
			linux16 7
			/vmlinuz-3.10.0-862.el7.x86_64 30
			root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
			crashkernel=auto 16
			linux16 7
			/vmlinuz-0-rescue-18ed42c1c89e4d28870e69320e88d637 50
			root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
			crashkernel=auto 16
	
	6.3  do-while 循环
		 语法:do statement while (condition)
			意义:至少执行一次循环体
	
	6.4 for循环
		语法:for(expr1;expre2;expr3) statement
		     
			 for(variable assignment;condition;iteration process) {for-body}
						
			[root@centos7 ~]#awk  '/^[[:space:]]*linux16/ {for(i=1;i<=NF;i++) {print $i,length($i)}}'  /etc/grub2.cfg 
			linux16 7
			/vmlinuz-4.20.3-1.0-xinzhoulinux 32
			root=UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f 46
			ro 2
			crashkernel=auto 16
			rhgb 4
			quiet 5
			LANG=en_US.UTF-8 16
			linux16 7

			特殊用法:
				能够遍历数组中的元素:
					语法:for(var in array) {for-body}
7、array

	关联数组:array[index-expression]
		index-expression:
			(1)可使用任何字符串:字符串要使用双引号:
			(2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”:
			
			若要判断数组中是否存在某元素,要使用“index in array”格式进行:
			weekdays["mon"]="Monday"
			
			[root@centos7 ~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
			Monday
			
			[root@centos7 ~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}'
			Tuesday

			[root@centos7 ~]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
			Tuesday
			Monday
			
			注意:var会遍历array中的每个索引:

[root@centos7 ~]#tail -4 /etc/fstab |awk '{print "hello: " $1,$2}' hello: UUID=576ed6fe-d3e8-403d-832f-2dc117ba8d2f / hello: UUID=6e6694fc-5a2f-47a1-b96b-509621e5fc1e /boot hello: UUID=1828df2b-47f3-442d-9681-ca17539861d9 /data hello: UUID=111bb92e-4d79-486a-afaf-38ba79856d30 swap

[root@centos7 ~]#awk -v FS=':' '{print $1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail operator games ftp nobody pegasus

[root@centos7 ~]#awk -v FS=':' -v OFS='=====' '{print $1,$3,$7}' /etc/passwd //FS: 输入字段分隔符, 默认为空白字符 OFS: 输出字段分隔符, 默认为空白字符 root=====0=====/bin/bash bin=====1=====/sbin/nologin daemon=====2=====/sbin/nologin adm=====3=====/sbin/nologin lp=====4=====/sbin/nologin sync=====5=====/bin/sync shutdown=====6=====/sbin/shutdown halt=====7=====/sbin/halt mail=====8=====/sbin/nologin operator=====11=====/sbin/nologin games=====12=====/sbin/nologin

[root@centos7 ~]#awk -v RS=' ' '{print}' /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin pegasus:x:66:65:tog-pegasus OpenPegasus

[root@centos7 ~]#awk -v RS=' ' -v ORS='###' '{print}' /etc/passwd // RS: 输入时的换行符 ORS: 输出时的换行符 root:x:0:0:root:/root:/bin/bash games:x:12:100:games:/usr/games:/sbin/nologin ftp:x:14:50:FTP###User:/var/ftp:/sbin/nologin nobody:x:99:99:Nobody:/:/sbin/nologin pegasus:x:66:65:tog-pegasus###OpenPegasus###WBEM/CIM###services:/var/lib/Pegasus:/sbin/nologin systemd-network:x:192:192:systemd###Network###Management:/:/sbin/nologin

[root@centos7 ~]#awk '{print NF}' /etc/fstab //NF: 字段数量 01 2 10 1 9 12 1 6 6 6 6

[root@centos7 ~]#awk '{print NR}' /etc/fstab //NR: 行数 1 2 3 4 5 6 7 8 9 10

[root@centos7 ~]#awk '{print FNR}' /etc/fstab /etc/issue //FNR: 各文件分别计数: 行数: 1 2 3 4 5 6 7 8 9 10 11 12 1 2 3

[root@centos7 ~]#awk 'BEGIN{print ARGC}' /etc/fstab /etc/issue //ARGC: 命令行参数的个数: 3

[root@centos7 ~]#awk 'BEGIN{print ARGV[0]}' /etc/fstab /etc/issue //ARGV: 数组,保存的是命令行所给定的各参数: awk [root@centos7 ~]#awk 'BEGIN{print ARGV[1]}' /etc/fstab /etc/issue //ARGV: 数组,保存的是命令行所给定的各参数: /etc/fstab [root@centos7 ~]#awk 'BEGIN{print ARGV[2]}' /etc/fstab /etc/issue //ARGV: 数组,保存的是命令行所给定的各参数: /etc/issue

[root@centos7 ~]#awk -v test="hello world" 'BEGIN{print test}' hello world [root@centos7 ~]#awk 'BEGIN{test="hello world";print test}' hello world

[root@centos7 ~]#awk -F: '{printf "Username: %s Uid: %d\n", $1,$3}' /etc/passwd //格式符用法 Username: root Uid: 0 Username: bin Uid: 1 Username: daemon Uid: 2 Username: adm Uid: 3 Username: lp Uid: 4 Username: sync Uid: 5 Username: shutdown Uid: 6 Username: halt Uid: 7 Username: mail Uid: 8 Username: operator Uid: 11

[root@centos7 ~]#awk -F: '{printf "Username: %19s Uid: %d\n", $1,$3}' /etc/passwd //格式符,修饰符, 默认右对齐 Username: root Uid: 0 Username: bin Uid: 1 Username: daemon Uid: 2 Username: adm Uid: 3 Username: lp Uid: 4 Username: sync Uid: 5 Username: shutdown Uid: 6 Username: halt Uid: 7 Username: mail Uid: 8 Username: operator Uid: 11 Username: games Uid: 12 Username: ftp Uid: 14 Username: nobody Uid: 99 Username: pegasus Uid: 66 Username: systemd-network Uid: 192

[root@centos7 ~]#awk -F: '{printf "Username: %-19s Uid: %d\n", $1,$3}' /etc/passwd // 19字符串的宽度, 加- 左对齐显示 Username: root Uid: 0 Username: bin Uid: 1 Username: daemon Uid: 2 Username: adm Uid: 3 Username: lp Uid: 4 Username: sync Uid: 5 Username: shutdown Uid: 6 Username: halt Uid: 7 Username: mail Uid: 8 Username: operator Uid: 11 Username: games Uid: 12 Username: ftp Uid: 14 Username: nobody Uid: 99 Username: pegasus Uid: 66