内容:
awk[options]'program'var=valu file
-f programfilevar=value file…
'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...
awk程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成
部基本格式:awk [options]'program'file..
statements;......}
stattements:对数据进行处理,放在{}内指明printprintf
啊我可执行时,由分割符分隔的字段(域)标记$1,$2..$n称为域标识。$0为所有域
第一步:执行BEGIN{action;… }语句块中的语句
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;…}语句块
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块
pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块
(2)输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式
tail –3 /etc/fstab|awk‘{print $2,$4}’
-F : '{sum+=$3}END{print sum}' /etc/passwd
awk-vFS=':''{print $1,FS,$3}'/etc/passwd(以:为分隔符取/etc/passwd第一第三字段)
awk–F:'{print $1,$3,$7}’ /etc/passwd
awk-v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’
/etc/passwd
awk -v RS=";"'{print $1,$3,$4}' f1(以分号为记录的分隔符,取记录的第1,3,4字段)
awk-vORS='##$#' {print $1,#$3,$4}f1
awk-F:'{print NF}' /etc/fstab,引用内置变量不用$
awk-F: '{print $(NF-1)}' /etc/passwd
awk '{print NR}' /etc/fstab(没有意义,只是输出行号)
awk -F:'{print NF,$0}' /etc/passwd(给/etcpasswd加入行号)
awk '{print FILENAME}’ /etc/fstab
awk 'BEGIN{print ARGC}' /etc/fstab/etc/inttab
awk 'BEGIN{print ARGV[0]}'f1test第一个参数为awk
awk 'BEGIN{printARGV[1],ARGV[2]}'test f1 显示第二第三个参数
awk 'BEGIN{printARGV[2]}' test f1
awk 'BEGIN{printARGV[ARGC-1]}' test f1两都表示第三被参数
awk -v test='hello gawk' '{print test}' /etc/fstab
awk -v test='hello gawk' 'BEGIN{print test}'
awk 'BEGIN{test="hello,gawk";printtest}'
awk –F: '{sex=“male”;print$1,sex,age;age=18}' /etc/passwd
cat awk script {print script,$1,$2}
awk-F: -f awkscriptscript=“awk” /etc/passwd
格式化输出:printf"FORMAT",item1,item2
5)别忘了FORMAT与item1之间有一个逗号:"FORMAT",item1
%d, %i:显示十进制整数
%s:显示字符串(常用)
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
awk -F: '{printf"%s",$1}' /etc/passwd不会自动换行(不加换行符感觉很乱),需要显式给出换行控制符,\n
•awk -F: '{printf"%s\n",$1}' /etc/passwd 加了换行符
初学者的错误:
awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
•awk -F: '{printf "Username: "%s\n",$1}' /etc/passwd("%s\n"与$1别忘了加逗号)
•awk-F:'{printf“Username: %s,UID:%d\n",$1,$3}'
•awk -F: '{printf"Username: %15s,UID:%d\n",$1,$3}' /etc/passwd
写成自定义格式是不要把printf写成pint下面的就是这样的错误
x/y, x^y, x%y
/=, %=, ^=
>=, <, <=
awk–F: '$0 ~ /root/{print $1}‘ /etc/passwd
•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
•awk -F: '!($3>=500) {print $3}' /etc/passwd
函数调用:function_name(argu1, argu2, ...)
条件表达式(三目表达式):
selector?if-true-expression:if-false-expression
逻辑:如果selector成立执行if-true-exprssione的内容,否则执行:if-false-expression的内容。?与:为固定格式造抄
•示例:用awk显示/etc/passwd中的系统用户和普通用户
awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or
SysUser";printf"%-15s:%-s\n",$1,usertype}' /etc/passwd
2)/regular expression/仅处理能够模式匹配到的行,需要用/ /括起来
awk '/^UUID/{print $1}' /etc/fstab
awk '!/^UUID/{print $1}' /etc/fstab
3) relational expression:关系表达式,结果为“真”才会被处理
1)如果没有指定:为空模式,匹配每一行(可以理解成4后面的描述)
4)如果PATTERN没有{action},说明省略{print $0},表示输出匹配到的整行(记录)如下:
awk -F: 'i=1;j=1{printi,j}'/etc/passwdi=1后面省略了{print $0}所以先输出整行,在输出i,j的值
awk '!0'/etc/passwd!0为1,1表示匹配整行,没有动作{action}表示输出整行,连起来表示输出整行
awk -F: '$NF ~/bash$/{print#$1,$NF}'/etc/passwd/bash$/是正则表达式
4.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
BEGIN/END模式
awk -F : 'BEGIN {print "USER USERID"} {print
$1":"$3} END{print "end file"}' /etc/passwd
•awk -F : '{print "USER USERID“;print $1":"$3} END{print "end file"}' /etc/passwd
•awk -F: 'BEGIN{print " USER UID \n---------------"}{print $1,$3}' /etc/passwd
.............................................................
seq 10 |awk ‘i=0’i=0为假不符合条件,不执行
seq 10 |awk ‘i=1’i=1为真,符合条件,执行。动作没有指定:为空模式,匹配每一行
seq 10 | awk 'i=!i‘因为i没有赋值所以i=0当i=0是!0为1,1为真 执行输出为1,执行过后i=1,!i为0,0为假不执行,此时i=0,!i=1执行,当i=1时!i=0,不执行
seq 10 | awk '{i=!i;print i}‘为命令seq 10 | awk 'i=!i‘中i的值
seq 10 | awk '!(i=!i)'因为i没有赋值所以i=0当i=0是!0为1,!(i=1)为0不执行,过后i=1
•seq 10 |awk -v i=1 'i=!i'i=1,赋值初始化,只执行一次,i=!1 ,i=0,为假,不执行,i=0,i=!0,i=1,为真执行,。。。
if-else语法:if(condition){statement;...}[else statement]
if(condition1){statement;...}else
if (condition2){statement2}else {statement3}
seq10 |awk ‘i=0’i=0为假不符合条件,不执行
seq 10 |awk 'i=1' i=1为真,符合条件,执行。动作没有指定:为空模式,匹配每一行
seq 10 | awk 'i=!i‘因为i没有赋值所以i=0当i=0是!0为1,1为真 执行输出为1,执行过后i=1,!i为0,0为假不执行,此时i=0,!i=1执行,当i=1时!i=0,不执行
seq 10 | awk '{i=!i;print i}‘为命令seq 10 | awk 'i=!i‘中i的值
seq 10 | awk '!(i=!i)'因为i没有赋值所以i=0当i=0是!0为1,!(i=1)为0不执行,过后i=1
(i=!1)i=0, !(i=0)为1,执行...
•seq 10 |awk -v i=1 'i=!i'i=1,赋值初始化,只执行一次,i=!1 ,i=0,为假,不执行,i=0,i=!0,i=1,为真执行,。。。
awk控制语句:
if-else语法:if(condition){statement;...}[else statement]
if(condition1){statement;...}else
if (condition2){statement2}else {statement3}
awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
awk'{if(NF>5) print $0}' /etc/fstab
awk-F: '{if($3>=1000) {printf"Common user:
%s\n",$1} else {printf"root or Sysuser: %s\n",$1}}' /etc/passwd
awk -F: '{if($3>=1000) printf "Common user:
%s\n",$1;
else printf "root or Sysuser: %s\n",$1}'
/etc/passwd
$1}'|awk'$NF>=80{print $1,$5}‘
awk'BEGIN{ test=100;if(test>90){print "very
good"}
"good"}else{print "no pass"}}'
语法:while(condition){statement;}
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 {statement;…}while(condition)
•awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print
total}‘
语法:for(expr1;expr2;expr3) {statement;…}
for(variable assignment;condition;iterationprocess)
语法:for(varin array) {for-body}
awk'/^[[:space:]]*linux16/{for(i=1;i<=NF;i++)
{print $i,length($i)}}' /etc/grub2.cfg
total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
time(total=0;for i in {1..10000};do
total=$(($total+i));done;echo $total)
time(for ((i=0;i<=10000;i++));do let
total+=i;done;echo $total)
{case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2;
...; default: statementn}
•awk 'BEGIN {sum=0;for(i=1;i<=100;i++)
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd
awk数组
•(2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
•若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
'BEGIN{weekdays["mon"]="Monday";
weekdays["tue"]="Tuesday";print
weekdays["mon"]}‘
•awk '{!arr[$0]++;print $0, arr[$0]}' dupfile
awk数组
•awk'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]
="Tuesday";for(iin weekdays) {print
weekdays[i]}}‘
•netstat-tan | awk'/^tcp/{state[$NF]++}END
{for(i in state) { print i,state[i]}}'
•awk'{ip[$1]++}END{for(iin ip) {print i,ip[i]}}'
/var/log/httpd/access_log
awk -F : '{line[$7]++}END{for(i in line){ print i,line[i]}}' /etc/passwd
其中因为line[$7]没有赋值默认为0,遍历中i代表数组line的下标为$7,line[i]为为line[$7]为次数
awk '/^tcp/{line[$NF]++}END{for(i in line){printi,line[i]}}' f1.log
netstat -nt | awk -F '[[:space:]:]+''/^tcp/{ip[$6]++}END{for(i in ip){printi,ip[i]}}'
netstat -tn | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'
awk'BEGIN{srand(); for (i=1;i<=10;i++)print
int(rand()*100) }'
直接写随机数是错误的,它需要种子srand()才能生成随机数
•sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s
echo "2008:08:08 08:08:08" | awk'sub(/:/,“-",$1)'
•gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
awk‘gsub(/:/,“-",$0)'
•split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…
awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}
END{for (iin count) {print i,count[i]}}'
system命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。
awk BEGIN'{system("hostname") }'
awk'BEGIN{score=100; system("echo your score is
" score) }'