awk:报告生成器,格式化文本输出。有多种版本:New awk(nawk),GNU awk(gawk)。CentOS中使用的是gawk
gawk:模式扫描和处理语言 linux
awk程序可由:BEGIN语句块、可以使用模式匹配的通用语句块(program)、END语句块,共3部分组成 pragram一般是被放在单引号中
经常使用选项:
-F "分隔符" 指明输入时用到的字段分隔符,若是不指定分隔符,默认以空格分隔
-V var=value 变量赋值 shell
awk变量有内置和自定义变量
经常使用内置变量:
变量名 | 做用
$0 | 表示一整行 |
$1-$n | 表示第一个字段到第n个字段 |
FS | 输入字段分隔符,默认为空白字符 |
OFS | 输出字段分隔符,默认为空白字符 |
RS | 输入记录分隔符,指定输入时的换行符 |
ORS | 输出记录分隔符,指定输出时的换行符 |
NF | 字段数量 |
NR | 记录号 |
FNR | 各文件分别记数,记录号 |
FILENAME | 当前处理文件的文件名 |
ARGC|命令行参数的个数,awk算第一个参数,中间语句不算参数 |
ARGV|数组,保存的是命令午所给定的各参数|express
[root@CentOS7 data]#awk 'BEGIN{print ARGV[0] }' /etc/fstab awk [root@CentOS7 data]#awk 'BEGIN{print ARGV[1] }' /etc/fstab /etc/fstab
自定义变量(区分字符大小写) vim
[root@CentOS7 data]#awk -v test='hello gawk' '{print test}' /etc/fstab hello gawk . . . hello gawk [root@CentOS7 data]#awk -v test='hello gawk' 'BEGIN{print test}' hello gawk [root@CentOS7 data]#awk 'BEGIN{test="hello,gawk";print test}' hello,gawk
printf命令
格式化输出:print "FORMAT",item1,item2... 数组
一、必须指定FORMAT
二、不会自动换行,须要显式给出换行控制符,\n
三、FORMAT中须要分别为后面第个item指定格式符
格式符:与item一一对应
%c:显示字符的ASCII码
%d,%i:显示十进制整数
%e,%E:显示科学计数法数值
%f:显示为浮点数
%g,%G以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示% bash
修饰符
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后数度,%3.1f表示显示到小数点后一位 dom
算术操做符 tcp
+、-、*、/、^、% 加减乘除乘取余
-x:转换为负数
+x:将字符串转换为数值 ide
字符串操做符:没有符号的操做符,字符串链接
赋值操做符 函数
=,+=,-=,*=,/=,%=,^=,++,--
比较操做符
==,!=,>,>=,<,<=
模式匹配符:
~:左边是否和右边匹配,包含
!~: 是否不匹配
逻辑操做符:与&&,或||,非!
条件表达式(三目表达式)
selector?if-true-expression:if-false-expression
若是selector 为真,执行if-true部分,为假,执行if-false部分
根据模式(pattern)条件,过滤匹配的行,再作处理
若是未指定:空模式,匹配第一行
/regular expression/ :仅处理可以与模式相匹配的行,须要用//括起来
[root@CentOS7 data]#awk '/^UUID/{print $1}' /etc/fstab UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 UUID=8ea0b7b5-109d-43b7-bd1a-f18c5f4ae5de UUID=f6d8e5da-09bf-480a-9089-a83d8cb674c5 UUID=74df8071-4517-4645-872e-976e8a5514e4
表示只显示以UUID开头的行的第一个字段
relational expression:关系表达式,结果为"真"才会实处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值line ranges:行范围 表示从哪行开始,到哪行结束
startline,endline:/pat1/,/pat2/不支持直接给出数字格式
示例:表示从以root开始的行,到以nobody开始的行[root@CentOS7 data]#awk '/^root/,/^nobody/{print $1}' /etc/passwd root:x:0:0:root:/root:/bin/bash . . . nobody:x:99:99:Nobody:/:/sbin/nologin [root@CentOS7 data]#
BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本以前执行一次
END{}:仅在文本处理完成以后执行一次
[root@CentOS7 data]#awk -F: 'BEGIN{print "USER USERID"}{print $1 ":" $3}END{print "END FILE"}' /etc/passwd USER USERID root:0 . . . END FILE
if-else语句
语法:if(条件){statement;...}[else statement]
if(){}else if(){}else{}
使用场景:对awk取得的整行或某个字段作条件判断
示例:显示ID大于等于1000的行的第一,第3字段[root@CentOS7 data]#awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd nfsnobody 65534 liuqiyou 1000[root@CentOS7 data]#awk -F: '{if($NF=="/bin/bash")print $1}' /etc/passwd root liuqiyou[root@CentOS7 data]#awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd root or Sysuser: root . . . root or Sysuser: tcpdump Common user: liuqiyou[root@CentOS7 data]#awk 'BEGIN{test=100;if(test>90){print "very good "}else if(test>60){print " goood"}else{print "no pass"}}' very goodwhile 循环
语法:while(条件){动做}
条件"真",进入循环;条件"假",退出循环
使用场景:
对一行内的多个字段逐一处理时使用
对数组中的各元素 逐一处理时使用
示例:[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i);i++}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-957.el7.x86_64 30 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5[root@CentOS7 data]#awk 'BEGIN{i=1;sum=0;while(i<=100){sum+=i;i++}print sum}' 5050do-while循环
语法:do{}while()
先执行一次循环体后作条件判断,最少执行一次[root@CentOS7 data]#awk 'BEGIN{total=0;i=0;do{total+=i;i++;}while(i<=100);print total}' 5050for循环
语法:for(i=0;i<=100;i++){动做}
特殊用法:遍历数组是的元素
for(i in array){print i,array[i]}[root@CentOS7 data]#awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){print $i,length($i)}}' /etc/grub2.cfg linux16 7 /vmlinuz-3.10.0-957.el7.x86_64 30 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5 LANG=en_US.UTF-8 16 linux16 7 /vmlinuz-0-rescue-64dc0677454740549e82eabaf3619f3c 50 root=UUID=95730fd4-d3a2-4af9-8311-46422db2ed23 46 ro 2 crashkernel=auto 16 rhgb 4 quiet 5[root@CentOS7 data]#awk 'BEGIN{for(i=1;i<=100;i++)sum+=i;print sum}' 5050switch语句
语法:switch(expression){case VALUE1 or /PEGEXP/:statement1;case VALUE2 or /REGEXP2/}break和continue
break 跳出整个循环,提早结束循环[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}' 2145continue 跳出本次循环,进入下一次循环
[root@CentOS7 data]#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}' 2500next:跳出本行循环,进入下一行循环
关联数组:array[index-expession]
index-expession:
一、可以使用任意字符串;字符串要使用双引号括起来
二、若是某数组元素事先不存在,在引用 时,awk会自动建立些元素,并将其值初始化为"空串"
三、若要判断数组中是否存在某元素,要使用"index in array"格式进行遍历[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}' Monday [root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["tue"]}' Tuesday去除重复的行
[root@CentOS7 data]#awk '{!line[$0]++;print $0,line[$0]}' /etc/passwd使用for循环遍历数组中的每一个元素
for(var in array){for-body}
var会遍历arrayr的每一个索引[root@CentOS7 data]#netstat -tan |awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}' LISTEN 9 ESTABLISHED 1[root@CentOS7 data]#awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print i,weekd asys[i]}}' tue mon
数值处理:
rand():返回0到1之间一个随机数
awk 'BEGIN{STAND();for(i=1;i<=10;i++)print int(rand()*100)}'
字符串处理:
length([s]):返回指定字符串的长度
[root@CentOS7 data]#awk -F: '{print length($0)}' /etc/passwd
sub(r,s,[t]):对t字符串搜索r表示的模式匹配的内容,并所有替换为s所表示的内容
[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'sub(/:/,"-",$1)' 2008-08:08 08:08:08
gsub(r,s[t]):对t字符串进行搜索r表示的模式匹配的内容,并所有替换为s所表示的内容
[root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$1)' 2008-08-08 08:08:08 [root@CentOS7 data]#echo "2008:08:08 08:08:08" |awk 'gsub(/:/,"-",$0)' 2008-08-08 08-08-08
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存到array所表示的数组中,第一个索引值为1,第二个索引值为2,...
[root@CentOS7 data]#netstat -tn | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}' 172.22.37.100 1
自定义函数
自定义函数格式
function name ( parameter, parameter, ... ) { statements return expression }
awk中调用shell命令
system命令
空格是awk中的字符串链接符,若是system中须要使用awk中的变量,可使用空格分隔,或者说除了awk的变量外其余一概用""引用起来[root@CentOS7 data]#awk 'BEGIN{system("hostname")}' CentOS7.localdomain[root@CentOS7 data]#awk 'BEGIN{score=100;system("echo your scores is "score)}' your scores is 100
将awk程序写成脚本,直接调用或执行
[root@CentOS7 data]#vim f1.awk #!/bin/awk {if($3>=1000)print $1,$3} [root@CentOS7 data]#awk -F: -f f1.awk /etc/passwd nfsnobody 65534 liuqiyou 1000
[root@CentOS7 data]#vim f2.awk #!/bin/awk -f #this is a awk script {if($3>=1000)print $1,$3} [root@CentOS7 data]#chmod +x f2.awk [root@CentOS7 data]#./f2.awk -F: /etc/passwd nfsnobody 65534 liuqiyou 1000
格式:awkfile var=value var2=value2...inputfile
注意:在BEGIN过程当中不可用。直到首行输入完成之后,变量才可用。能够能完-v参数,让awk在执行BEGIN以前获得变量的值。命令行每个指定的变量都要一个-v参数
[root@CentOS7 data]#vim test.awk #!/bin/awk -f {if($3>=min && $3<=max)print $1,$3} [root@CentOS7 data]#chmod +x test.awk [root@CentOS7 data]#./test.awk -F: min=100 max=200 /etc/passwd systemd-network 192 abrt 173 rtkit 172 pulse 171 qemu 107 usbmuxd 113