三剑客-AWK命令详解

实验名称:Awk命令(脚本编程)
实验目的:进行实验,熟悉使用awk命令
实验环境:CentOS7 (1台)
实验步骤:
1、Awk脚本基础结构:
一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语 句块、END语句块3部分组成,这三个部分是可选的。任意一个部 分都可以不出现在脚本中,脚本通常是被单引号或双引号中
[root@bogon~]# awk ‘BEGIN{ i=0 } { i++ } END{ print i }’ /etc/passwd
43
//使用awk命令统计行数
2、Awk工作原理:
awk ‘BEGIN{commands } pattern{ commands } END{ commands }’
第一步:执行BEGIN{
commands }语句块中的语句;
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{
commands }语句块
例:[root@bogon ~]# echo -e “A 1\nB 2\nC 3\nD 4”| awk ‘BEGIN{ print"Start" } { print } END{ print “End” }’
Start
A 1
B 2
C 3
D 4
End
在这里插入图片描述

当使用不带参数的print时,它就打印当前行,当print的参数是以逗号进行分隔时,打印时则以空格作为定界符。在awk的print语句块中双引号是被当作拼接符使用
[root@bogon~]# echo | awk ‘{ sed1=“j”; sed2=“h”; sed3=“h”;print sed1,sed2,sed3; }’
j h h
双引号拼接使用:
[root@bogon~]# echo | awk ‘{ sed1=“j”; sed2=“h”; sed3=“h”;print sed1"=“sed2”="sed3; }’
j=h=h
在这里插入图片描述
3、Awk内置变量(预定义变量)
[root@bogon~]# echo -e “line1 f2 f3\nline2 f4 f5\nline3 f6 f7” | awk '{print"Line No:“NR”, No of fields:"NF, “$0=”$0,
“$1=”$1, “$2=”$2, “$3=“KaTeX parse error: Expected 'EOF', got '}' at position 2: 3}̲' ![在这里插入图片描述](…NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段,其他以此类推
[root@bogon~]# echo -e “line1 f2 f3\n line2 f4 f5” | awk ‘{print $NF}’
[root@bogon~]# echo -e “line1 f2 f3\n line2 f4 f5” | awk ‘{print $(NF-1)}’
在这里插入图片描述
打印每一行的第二和第三个字段:
[root@bogon~]# awk ‘{ print $2,$3 }’ /etc/passwd
在这里插入图片描述
统计文件中的行数:
[root@bogon~]# awk ‘END{ print NR }’ /etc/passwd
43
每一行中第一个字段值累加:
[root@bogon~]# seq 5 | awk 'BEGIN{ sum=0; print “总和:” } {print $1”+”; sum+=KaTeX parse error: Expected 'EOF', got '}' at position 3: 1 }̲ END{ print "等于…RY ‘{ print VARIABLE }’
1000
另一种传递外部变量方法:
[root@bogon~]# aq=“10”
[root@bogon~]# ws=“20”
[root@bogon~]# echo | awk ‘{ print y1,y2 }’ y1= a q y 2 = aq y2= aqy2=ws
10 20
当输入来自于文件时使用:
[root@bogon~]# awk ‘{ print y1,y2}’ y1=@aq y2=@ws /etc/passwd
在这里插入图片描述

//以上方法中,变量之间用空格分隔作为awk的命令行参数跟随在BEGIN、{}和
END语句块之后
5、Awk运算与判断:
作为对条件转移指令的一部分,关系判
断是每种程序设计语言都具备的功能,awk也不例外,awk中允许 进行多种测试,作为样式匹配,还提供了模式匹配表达式~(匹配)
和~!(不匹配)

算术运算符:
在这里插入图片描述[root@bogon~]# awk ‘BEGIN{a=“b”;print a++,++a;}’
0 2
//所有用作算术运算符进行操作,操作数自动转为数值,非数值都变为0

赋值运算符:
在这里插入图片描述
// a+=5; 等价于:a=a+5; 其它类同
逻辑运算符:
[root@bogon~]# awk ‘BEGIN{a=1;b=2;print (a>5 && b<=2),(a>5 || b<=2);}’
0 1
正则运算符:在这里插入图片描述
[root@bogon~]# awk ‘BEGIN{a=“100testa”;if(a ~ /^100*/){print “ok”;}}’
Ok

关系运算符:
在这里插入图片描述
[root@bogon~]# awk ‘BEGIN{a=11;if(a >= 9){print “ok”;}}’
Ok
//> < 可以作为字符串比较,也可以用作数值比较,关键看操作数如果是字符串就会转换为字符串比较。两个都为数字 才转为数值比较。字符串比较:按照ASCII码顺序比较

其它运算符:
在这里插入图片描述
[root@bogon~]# awk ‘BEGIN{a=“b”;print
a==“b”?“ok”:“err”;}’
ok

[root@bogon~]#awk’BEGIN{a=“b”;arr[0]=“b”;arr[1]=“c”;print
(a in arr);}’
0
[root@bogon~]#awk’BEGIN{a=“b”;arr[0]=“b”;arr[“b”]=“c”;print
(a in arr);}’
1
在这里插入图片描述
运算级优先级表:
在这里插入图片描述
6、Awk高级输入输出
awk中next语句使用:在循环逐行匹配,如果遇到next,就会跳过当前行,直接忽略下面语句。而进行下一行匹配。next语句一般用于多行合并:
[root@bogon~]# vim y.txt
[root@bogon~]# cat y.txt
[root@bogon~]# awk ‘NR%2==1{next}{print NR,$0;}’ y.txt在这里插入图片描述
//当记录行号除以2余1,就跳过当前行。下面的print NR,$0也不会执行。下一行开始,程序有开始判断NR%2值。这个时候记录行号是:2 ,就会执行下面语句块:‘print NR,$0’
读取下一条记录:
分析发现需要将包含有“web”行进行跳过,然后需要将内容与下面行合 并为一行:
[root@bogon~]# vim y.txt
[root@bogon~]# cat y.txt
[root@bogon~]# awk ‘/^web/{T=$0;next;}{print T":\t"$0;}’ y.txt
在这里插入图片描述
如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误, 例如打开文件失败,就返回-1
awk getline从整体上来说,用法说明:
当其左边无管道符|或当其右边无重定型符<时:getline作用于当前文件,读入当前文件的第一行给其后跟的变量var或$0(无变量),应该注意到,由于awk在处理getline之前已经读入了一行,所以getline得到的返回结果是隔行的。
当其左边有管道符|或当其右边有重定型符<时:getline则作用于定向输入文件,由于该文件是刚打开,并没有被awk读入一行,只是getline读入,那么getline返回的是该文件的第一行,而不是隔行。
执行linux的date命令,并通过管道输出给getline,然后再把输出赋值给自定义变量
out,并打印它:
[root@bogon~]# awk ‘BEGIN{ “date” | getline out; print out }’
2020年 12月 03日 星期四 17:17:45 CST
执行shell的date命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给out,split函数把变量out转化成数组mon,然后打印数组mon的第二个元素:
[root@bogon ~]# awk ‘BEGIN{ “date” | getline
out; split(out,mon); print mon[2] }’ y.txt
12月
命令ls的输出传递给geline作为输入,循环使getline从ls的输出中读取一行,并把它打印到屏幕。这里没有输入文件,因为BEGIN块在打开输入文件前执行,所以可以忽略输入文件:
[root@bogon ~]# awk ‘BEGIN{ while( “ls” |
getline) print }’
在这里插入图片描述
awk中允许在程序中关闭一个输入或输出文件,方法是使用awk的close语 句
close(“filename”)
// filename可以是getline打开的文件,也可以是stdin,包含文件名的变量或者getline使 用的确切命令。或一个输出文件,可以是stdout,包含文件名的变量或使用管道的确切命令

awk中允许用如下方式将结果输出到一个文件:
[root@bogon~]# echo | awk ‘{printf(“hello word!\n”) > “y.txt”}’
[root@bogon~]# cat y.txt
hello word!

[root@bogon~]# echo | awk ‘{printf(“hello man!\n”) >> “y.txt”}’
[root@bogon~]# cat y.txt
hello word!
hello man!
在这里插入图片描述
设置字段定界符:
默认的字段定界符是空格,可以使用-F
“定界符” 明确指定一个定界符:
[root@bogon~]# awk -F: ‘{ print $NF }’ /etc/passwd

[root@bogon~]# awk ‘BEGIN{ FS=":" } { print $NF }’ /etc/passwd
在这里插入图片描述
在这里插入图片描述
//在BEGIN语句块中还可以用OFS=“定界符”设置输出字段的定界符
7、流程控制语句:
条件判断语句:
在linux
awk的while、do-while和for语句中允许使用break,
continue语句来控制流程走向,也允许使用exit这样的语句来退出
条件判断语句:
(1)if(表达式)
语句1
else
语句2

(2)If(表达式)
{语句1}
else
if(表达式)
{语句2}
else
{语句3}

格式中语句1可以是多个语句,为了方便判断和阅读, 最好将多个语句用{}括起来。
awk分枝结构允许嵌套,其格式为:
[root@bogon~]# vim jj.sh
[root@bogon~]# sh jj.sh
very good //执行结果:very good

在这里插入图片描述
循环语句–while语句
while(表达式)
{语句}
//执行结果:5050
在这里插入图片描述
循环语句–for循环:
格式1:
for(变量 in 数组)
{语句}
例:
[root@bogon ~]# awk ‘BEGIN{ for(k in
ENVIRON){ printk"="ENVIRON[k]; } }’
在这里插入图片描述
//执行结果: TERM=linuxG_BROKEN_FILENAMES=1 … …
格式2:
for(变量;条件;表达式)
{语句}
例:
[root@bogon
~]# awk ‘BEGIN{ total=0; for(i=0;i<=100;i++){ total+=i; } print total; }’
5050 //执行结果:5050
循环语句–do循环:
do
{语句}
while(条件)
[root@bogon
~]# awk ‘BEGIN{ total=0; i=0; do {total+=i;i++;} while(i<=100) print total; }’
5050 //执行结果:5050
循环语句–其他语句:
break当break 语句用于while 或 for 语句时,导致退出程序循环。 continue当continue语句用于 while 或
for 语句时,使程序循环移动到 下一个迭代。
next能够导致读入下一个输入行,并返回到脚本的顶部。这可以避免对当 前输入行执行其他的操作过程。
exit 语句使主输入循环退出并将控制转移到END,如果END存在的话。如果 没有定义END规则,或在END中应用exit语句,则终止脚本的执行。
8、数组应用:
数组的定义:
数字做数组索引(下标):
Array[1]=“sun”
Array[2]=“kai”
字符串做数组索引(下标):
Array[“first”]=“www”
Array[“last”]=“name”
Array[“birth”]=“1987”
//使用中print Array[1]会打印出sun;使用print Array[2]会打印出kai;使用print[“birth”]
会得到1987
读取数组的值:
{ for(item inarray) {print array[item]}; } //输出的顺序是随机的
{for(i=1;i<=len;i++) {print array[i]}; } // Len是数组的长度
数组相关函数:
得到数组长度:
[root@bogon ~]# awk ‘BEGIN{info=“it is a
test”;lens=split(info,tA," ");print length(tA),lens;}’
4 4
length返回字符串以及数组长度,split进行分割字符串为数组,也会返回分割得到数组长度
[root@bogon~]# awk ‘BEGIN{info=“it is a test”;split(info,tA," ");printasort(tA);}’
4
asort对数组进行排序,返回数组长度
输出数组内容(无序,有序输出):
[root@bogon~]# awk ‘BEGIN{info=“it is a test”;split(info,tA," ");for(k
in tA){print k,tA[k];}}’
4 test
1 it
2 is
3 a
//数组下标是从1开始,与C数组不一样
判断键值存在以及删除键值:
错误的判断方法:
[root@bogon
~]# awk
‘BEGIN{tB[“a”]=“a1”;tB[“b”]=“b1”;if(tB[“c”]!=“1”){print"no found";};for(k in tB){print k,tB[k];}}’
no found
a a1
b b1
c
//tB[“c”]没有定义,但是循环时候,发现已经存在该键值,它的值 为空,这里需要注意,awk数组是关联数组,只要通过数组引用它的key,就会自动创建 改序列
判断键值存在以及删除键值:
正确判断方法:
[root@bogon~]#awk’BEGIN{tB[“a”]=“a1”;tB[“b”]=“b1”;if(
“c” in tB){print “ok”;};for(k in tB){print k,tB[k];}}’
a a1
b b1
// if(key in array)通过这种方法判断数组中是否包含key键值
删除键值:
[root@bogon~]# awk ‘BEGIN{tB[“a”]=“a1”;tB[“b”]=“b1”;delete
tB[“a”];for(k in tB){print k,tB[k];}}’
b b1
// delete array[key]可以删除,对应数组key的,序列值
二维、多维数组使用:
awk的多维数组在本质上是一维数组,更确切一点,awk在存储上并不支持 多维数组。awk提供了逻辑上模拟二维数组的访问方式。例如array[2,4]=1这样的访问是允许的。awk使用一个特殊的字符串
SUBSEP(\34)作为分割字段,在上面的例子中,关联数组array存储的键值
实际上是2\344
类似一维数组的成员测试,多维数组可以使用if ( (i,j) in array)这样的语法, 但是下标必须放置在圆括号中。类似一维数组的循环访问,多维数组使用 for ( item in array )这样的语法遍历数组。与一维数组不同的是,多维数组 必须使用split()函数来访问单独的下标分量
[root@bogon~]#awk ‘BEGIN{ for(i=1;i<=9;i++){ for(j=1;j<=9;j++){ tarr[i,j]=ij;printi,"",j,"=",tarr[i,j];
} } }’
在这里插入图片描述
另一种方法:
[root@bogon
~]# awk ‘BEGIN{ for(i=1;i<=9;i++){
for(j=1;j<=9;j++){
tarr[i,j]=ij; } } for(m in
tarr){ split(m,tarr2,SUBSEP); print
tarr2[1],"
",tarr2[2],"=",tarr[m]; } }’
在这里插入图片描述
9、内置函数:
awk内置函数,主要分以下3种类似:算数函数、字符串函数、其它一般函数、 时间函数在这里插入图片描述
算术函数:
[root@bogon~]#awk’BEGIN{OFMT="%.3f";fs=sin(1);fe=exp(10);fl=log(10);fi=int(3.1415);print
fs,fe,fl,fi;}’
0.841
22026.466 2.303 3
// OFMT 设置输出数据格式是保留3位小数
获得随机数:
[root@bogon~]# awk’BEGIN{srand();fr=int(100*rand());print fr;}’
24
在这里插入图片描述
字符串函数:
在这里插入图片描述
在这里插入图片描述
gsub,sub使用:
[root@bogon~]# awk ‘BEGIN{info=“this is a
test2010test!”;gsub(/[0-9]+/,"!",info);print info}’
this is a
test!test!
//在 info中查找满足正则表达式“/[0-9]+/”用“!”替换,并将替换后的值赋info,如果 未给出info值,则默认赋给$0。
查找字符串(index使用):
[root@bogon
~]# awk ‘BEGIN{info=“this is a test2010test!”;print
index(info,“test”)?“ok”:“no found”;}’
Ok //如未找到,返回0
正则表达式匹配查找(match使用):
[root@bogon~]# awk ‘BEGIN{info=“this is a test2010test!”;print
match(info,/[0-9]+/)?“ok”:“no found”;}’
Ok
截取字符串(substr使用):
[root@bogon~]# awk ‘BEGIN{info=“this is a test2010test!”;printsubstr(info,4,10);}’
s is a tes //从第 4个 字符开始,截取10个长度字符串字符串分割(split使用):

[root@bogon~]# awk ‘BEGIN{info=“this is a test”;split(info,tA,"");print length(tA);for(k in tA){print k,tA[k];}}’
在这里插入图片描述
//分割info,创建动态数组tA,这里比较有意思,awk for …in循环,是一个无序的循环。 并不是从数组下标1…n,因此使用时候需要注意
格式化字符串输出(sprintf使用):
格式化字符串格式:其中格式化字符串包括两部分内容:一部分是正常字符,这些字 符将按原样输出; 另一部分是格式化规定字符,以"%“开始,后跟一个或几个规定字符, 用来确定输出内容格式
在这里插入图片描述
[root@bogon~]# awk 'BEGIN{n1=124.113;n2=-1.224;n3=1.2345;printf(”%.2f,%.2u,%.2g,%X,%o\n",n1,n2,n3,n1,n1);}’
124.11,18446744073709551615,1.2,7C,174

一般函数:
在这里插入图片描述

打开外部文件(close用法):
[root@bogon~]#awk’BEGIN{while(“cat/etc/passwd”|getline){print$0;};close("/etc/passwd");}’

在这里插入图片描述
逐行读取外部文件(getline使用方法):
[root@bogon~]# awk ‘BEGIN{while(“cat /etc/passwd"getline{print$0;};close(”/etc/passwd");}’
在这里插入图片描述
[root@bogon~]# awk ‘BEGIN{print “Enter your name:”;getline name;print name;}’
在这里插入图片描述
调用外部应用程序(system使用方法):
[root@bogon~]# awk ‘BEGIN{b=system(“ls -al”);print b;}’在这里插入图片描述
// b为返回值,即执行结果
时间函数:
指定时间(mktime使用):
[root@bogon~]#awk’BEGIN{tstamp=mktime(“2001 01 01 12 1212”);printstrftime("%c",tstamp);}’
2001年01月01日 星期一
12时12分12秒
[root@bogon~]#awk’BEGIN{tstamp1=mktime(“2001 01 01 12 1212”);tstamp2=mktime(“2001 02 01 0 0 0”);print tstamp2-tstamp1;}’
2634468 //自1970年1月1日0:00至今(秒数)
求2个时间段中间时间差,介绍了strftime使用方法
[root@bogon~]#awk’BEGIN{tstamp1=mktime(“2001 01 01 12 12 12”);tstamp2=systime();print tstamp2-tstamp1;}’
628674116 //自1970年1月1日0:00至今(秒数)
strftime日期和时间格式说明符:
在这里插入图片描述
至此,awk实验完成!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值