什么是awk?
awk:Aho,Weinberger,Kernighan,报告生成器,格式化文本输出
有多种版本:New awk(nawk),GNU awk(gawk)
gawk:模式扫描的处理语言
基本用法:
awk [options] 'program' var=value file...
awk [POSIX or GNU style options] -f programfile [--] file ...linux
基本格式:
awk [options] 'program' file...
program:pattern{action statements;...}
读入文件一行,检查是否符合pattern,是就执行action statments
BEGIN:没有读取文件前,先执行BEGIN
END:读取完成文件后,执行END
省略action,则默认执行 print $0 的操做
在{}中,$1 $2要用,才能够分割,用空格不行,能够用"\t"
分割符:
读入行分割成$1 $2,默认是空格,无论几个空格都压缩成一个,-F设置分隔符
域:
行的全部字段$0为全部域
记录:
文件的每一行称为记录,能够把多选,一行中的一部分做为记录,能够利用-v RS=“”来定义记录分隔符正则表达式
-F 列分隔符 -v 变量赋值,变量能够延伸到下一行 FS=":" 列分隔符,FS=$PATH,能够引用shell中的变量 field space awk -v FS=$S '{pirnt $1,$3}' /etc/passwd OFS=":" 输出时列分隔符 awk -v OFS=*** '{print $1OSF$3}' /etc/passwd RS="" 输入记录分隔符,指定输入时的换行符 record space awk -v RS="" '' ORS="" 输出记录分隔符,指定时不用在action中引用有有 awk -v ORS="" 自定义变量: awk -v var=123 awk -F: '{title="hello"; print $1,title}' /etc/passwd NF 字段数 number field awk -F: '{print NF}' /etc/passwd awk -F: '{print $NF}' /etc/passwd 最后一段 awk -F: '{print $(NF-1)}' /etc/passwd 倒数第二段 NR 记录数 number record awk -F: '{print NR,$1}' /etc/passwd 打印第一行的行号 FNR 各文件分别计数,记录号 awk '{print FNR}' /etc/fstab /etc/inittab FILENAME 当前文件名 awk '{print FILENAME}' /etc/fstab ARGC 命令行参数的个数 awk '{print ARGC}' /etc/fstab ARGV 数组,保存的是命令行所给定的各参数 awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab -f awkScript 使用扩展正则表达式来定义-F后的分隔符 df | grep "/dev/sd" | awk -F"[[:space:]]+|%" '{print $5}' (以多个连续空格或%为分隔符)  df | awk -F" +|%" '/^\/dev\/sd/{print $1,$5}' 
printf命令
printf "FORMAT",item1,item2,...
一、必须指定FORMAT
二、不会自动换行,须要显示给出换行控制符,\n1
三、FORMAT中须要分别为后面每一个item指定格式符
格式符:与item一一对应
%c:显示字符的ASCII码
%d, %i:显示十进制整数
%e, %E:显示科学计数法数值
%f:%.2f,右对齐%10.2f,右对齐%-10.2f,显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
修饰符
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1fshell
显示数值的正负符号 %+d
echo "100.123" | awk '{printf "The is a %d"kk,$0}'
awk的操做符
算术操做符:x+y x%y +x -x
字符串操做符:没有符号的操做符,字符串链接
赋值操做符:= += -= *= /= %= ^= ++ --
比较操做符:==, !=, >, >=, <, <=
模式匹配符:~ !~
awk -F: '$3 ~ /107/{print $1}' /etc/passwd 匹配第3列中等于107的行的用户名
df | awk '$0 ~ "^/dev/sd" {print $0}' 打印匹配df命令以^/dev/sd开头的行
逻辑操做符:与&&,或||,非!
awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
awk -F: ‘!($3==0) {print $1}' /etc/passwd
条件表达式(三目表达式)
selector?if-true-expression:if-false-expression
awk -F: '{$3>=1000?usertype="Common User":usertype=" SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
PATTERN:根据pattern条件,过滤匹配的行,再作处理
(1)若是未指定:空模式,匹配每一行
(2) /regular expression/:仅处理可以模式匹配到的行,须要用/ /括起来
awk '/^UUID/{print $1}' /etc/fstab
awk '!/^UUID/{print $1}' /etc/fstab
(3) relational expression: 关系表达式,结果为“真”才会被处理
只要是awk -F: '""{print $1,$3}' /etc/passwd中{print $1,$3}前""是空就是,只要有内容都是真
字符串不空为真,数值不为0为真
真:结果为非0值,非空字符串
假:结果为空字符串或0值
(4) line ranges:行范围
startline,endline:/pat1/,/pat2/ 不支持直接给出数字格式
awk -F: ‘/^root\>/,/^nobody\>/{print $1}' /etc/passwd
awk -F: ‘(NR>=10&&NR<=20){print NR,$1}' /etc/passwd
seq 10 | awk 'NR>2;NR<=5'
打印所有行,且3 4 5 打印两遍
(5) BEGIN/END模式
BEGIN{}:仅在开始处理文件中的文本以前执行一次
END{}:仅在文本处理完成以后执行一次express
seq 10 | awk 'i=0' 这个awk是默认省略了{print $0} seq 10 | awk 'i=!i' 一、对空i取反为非空,打印 二、对非空i取反,不打印,这样循环,打印奇数行 seq 10 | awk '!(i=!i)'
经常使用的action分类
•(1) Expressions:算术,比较表达式等
•(2) Control statements:if, while等
•(3) Compound statements:组合语句
•(4) input statements
•(5) output statements:print等数组
{ statements;… } 组合语句
if(condition) {statements;…}
if(condition) {statements;…} else {statements;…}
while(conditon) {statments;…}
do {statements;…} while(condition)
for(expr1;expr2;expr3) {statements;…}
break
continue
delete array[index]
delete array
exittcp
if-else语句
awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
df -h|awk -F% '/^\/dev/{print $1}'|awk '$NF>=80{print $1,$5}‘ide
while语句
awk '/^[[:space:]]linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg
awk '/^[[:space:]]linux16/{i=1;while(i<=NF) {if(length($i)>=10) {print $i,length($i)}; i++}}' /etc/grub2.cfg函数
do-while语句
awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}'spa
for循环语句
语法:for(expr1;expr2;expr3) {statement;…}
awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg命令行
switch语句
语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
break和continue
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}'
awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==66)break;sum+=i}print sum}'
awk '!line[$0]++' fl.txt 忽略重复行,第一次f1.txt的第一行为line["123"]为空,line["123"]++=line["123"]=1
awk '!line[$0]++{pirint $0 line[$0]}' f1.txt 查看
awk '{!line[$0]++; pirint $0 line[$0]}' f1.txt
awk数组
关联数组:array[index-expression]
index-expression
(1)、可以使用任意字符串,字符串要使用双引号括起来
(2)、若是某数组元素事先不存在,在引用时,awk会自动建立此元素,并将某值初始化为"空串"
(3)、若要判断数组中是否存在某元素,要使用"index in array",格式进行遍历
若要遍历数组中的每一个元素,可以使用for循环
for(var in array) {for-body}
注意:var会遍历array的每一个索引
awk‘BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday"; for(i in weekdays) {print weekdays[i]}}'
netstat -tan | awk '/^tcp/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
利用函数求男女的平均数 name score gender a 100 m b 99 f c 80 f awk 'NR!=1{sum[$3]+=$2;num[$3]++}END{for(i in sum)print i,num[i];or(i in sum)print i,num[i];}'
函数rand():返回0和1之间的一个随机数srand()有种子才能形成随机数awk 'BEGIN{srand();print rand()}'awk 'BEGIN{srand();print int(rand()*100)}'字符串处理:length([s]):返回指定字符串的长度sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为secho "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并所有替换为s所表示的内容split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…array[1]切割的第一列,array[2]切割后...ss -tn | awk '/^ESTAB{split($NF,ip,":");count[ip[1]]++};END{for(i in count)print i,count[i]}' 自定义函数格式:function name ( parameter, parameter, ... ) {statementsreturn expression}示例:cat fun.awkfunction max(x,y) {x>y?var=x:var=yreturn var}BEGIN{a=3;b=2;print max(a,b)}awk -f fun.awk调用shell中的命令awk 'BEGIN{system("hostname")}'awk 'BEGIN{score=100;system("echo your score is " score)}'