主要内容
AWK高级应用
awk的语法比sed的更加高级,原因在于awk提供了更加完整的编程语言语法支持,例如自定义变量,控制结构,函数等。
自定义变量
除了内置变量,awk还允许使用自定义变量。和shell变量不一样,awk变量的定义和使用都不需要$
符号。
1 2 |
[centos7-server ~]# awk 'BEGIN{TODAY="Saturday"; print TODAY}' Saturday |
awk变量可以是任意长度的字符、数字和下划线,但是变量开头不能是数字。
变量类型除了是字符串外,还可以是数字,整数和浮点数皆可:
1 2 |
[centos7-server ~]# awk 'BEGIN{x=10; x=x+20*3; print x}' 70 |
通过参数传递变量值
参数传递的好处是可以动态设置变量的值,从而灵活地控制脚本的行为
1 2 3 4 5 |
[centos7-server ~]# cat script BEGIN{print "variable n="n} [centos7-server ~]# awk -f script -v n=10 variable n=10 |
由于我们希望把n传递给BEGIN代码块,因此需要使用-v选项,否则BEGIN代码块无法读取n的值。
使用数组
一般编程语言中数组有两种:索引数组和关联数组,索引数组是以数字为索引,关联数组是以任意字符串为索引,即我们常说的词典(dictionary)。
1 |
awk 'BEGIN{capital["china"]="beijing"; print capital["china"]}' |
使用索引数组:
1 2 |
[centos7-server ~]# awk 'BEGIN{var[1]=10; var[2]=20; print var[1]+var[2]}' 30 |
删除数组内容:
使用delete,可以删除数组变量的值
1 2 3 |
[centos7-server ~]# awk 'BEGIN{var[1]=10; var[2]=20; delete var[2]; print var[1]"----"; print var[2]"----"}' 10---- ---- |
delete后,var[2]的值就不存在了。
使用正则表达式
sed和awk之所以强大,都是因为正则表达式背后的支持。在awk中使用正则表达式和sed一样简单。
打印/etc/passwd文件中包含root的行的第一列和最后一列:
1 2 3 |
[centos7-server ~]# awk -F: '/root/ {print $1,$NF}' /etc/passwd root /bin/bash operator /sbin/nologin |
使用匹配操作符(~)
匹配操作符~
返回一个布尔值,是或者否。上面的例子打印所有包含root的行。但是如果只希望打印第一列是root的行,那么就可以使用这个操作符:
1 2 |
[centos7-server ~]# awk -F: '$1 ~ /root/ {print $1,$NF}' /etc/passwd root /bin/bash |
这里~
操作符的作用是对比第一列是否和/root/匹配,它有点类似match的意思:if $1 match root。
取反(!)
匹配操作符可以被感叹号取反,即不匹配的行:
1 |
[centos7-server ~]# awk -F: '$1 !~ /root/ {print $1,$NF}' /etc/passwd |
列出第一列($1)不包含root的行。
算数表达式
awk可用的算数表达式有:==、<=、<、>=、>。
打印组id为零的用户名。
1 2 3 4 5 6 |
[centos7-server ~]# gawk -F: '$4==0 {print $1}' /etc/passwd root sync shutdown halt operator |
结构化语句
awk提供了常见的流控制语句,例如if..else,while循环、do…while循环,for循环。
使用if…else
1 2 3 4 5 6 |
[centos7-server ~]# awk -F: '{ if ($1 ~ /root/){print $1, $NF} else {print "nothing matched"}}' /etc/passwd root /bin/bash nothing matched nothing matched nothing matched ...省略更多输出... |
例子中如果找到第一列开头是root的则打印改行的第一列和最后一列,否则打印nothing matched。
使用while循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[centos7-server ~]# cat script2 BEGIN{ var[1]=10 var[2]=20 var[3]=30 i=1 while (i<4) { print var[i] i++ } } |
执行结果:
1 2 3 4 |
[centos7-server ~]# awk -f script2 10 20 30 |
使用for循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
[centos7-server ~]# cat script3 BEGIN{ var[1]=10 var[2]=20 var[3]=30 for (i=1; i<4; i++) { print var[i] } } [centos7-server ~]# awk -f script3 10 20 30 |
使用函数
awk内建了大量的函数,例如字符串函数,I/O函数,时间函数等,具体可以使用pinfo gawk命令查看与function有关的章节。
使用时间函数的例子:
1 2 |
[centos7-server ~]# awk 'BEGIN{date=systime(); day=strftime("%Y-%m-%d", date); print day}' 2018-03-24 |
自定义函数
通过关键字function定义自己的函数,语法:
1 2 3 4 |
function name([variable]) { statements } |
例如创建一个打印当前时间的函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[centos7-server ~]# cat script4 function printtime() { date = systime() day = strftime("%Y-%m-%d", date) print day } BEGIN{ printtime() } [centos7-server ~]# awk -f script4 2018-03-24 |
函数要在使用之前被定义,但函数不能在花括号中定义:
1 2 3 4 5 6 7 8 9 |
[centos7-server ~]# awk ' > function myprint() > { > print "hello" > } > BEGIN{ > myprint() > }' hello |
单引号开始后马上定义函数。
转载请注明:Pure nonsense » SHELL程序设计(十一)AWK高级应用