awk是一种编程语言,gawk是目前最新的版本,当前的Linux版本用的都是gawk,利用gawk可以实现数据查找、抽取文件中数据、创建管道流命令等功能,awk实际是/bin/gawk的链接。
4.3.1 awk编程模型 awk程序由一个主输入循环main input loop维持,主输入循环反复执行,直到终止条件被触发,主输入循环自动依次读取输入文件行,以供处理,而处理文件行的动作是由程序员添加的。 awk还定义了两个特殊的字段:BEGIN和END,BEGIN用于在主输入循环之前执行,即在未读取输入文件之前执行,END则相反,用于在主输入循环之后执行,即在读取输入文件行完毕后执行。
4.3.2 awk调用方法 跟sed类似,也有三种方式: ① 在shell命令行直接输入命令调用,格式为: ② 将awk程序段插入脚本文件,然后通过awk命令调用它,格式为: awk -f awk脚本文件 输入文件 ③ 将sed命令插入脚本文件后,将该文件变成可执行,然后直接执行,不过需要一#!/bin/awk -f 开头 ./awk脚本文件 输入文件
4.4.1 awk模式匹配 # awk '/^$/{print "this is a blank line."}' input --> 打印空白行,遇到空白行就打印一句话 第三种调用方式,先写个src.awk脚本文件: Bash代码
然后chmod u+x src.awk,然后./src.awk input即可
4.4.2 记录和域 awk将每个输入文件行定义为记录,行中每个字符串定义为域,域之间用空格、Tab键或其他符号进行分割,称之为分隔符。 $1表示第一个域,$2表示第二个域以此类推。注:$0表示所有的域
使用 -F 选项指定分隔符: # awk -F "\t" '{print $3}' test.txt 还可以通过设置FS的值改变分隔符: # awk 'BEGIN {FS=","} {print $1}' test.txt # awk 'BEGIN {FS="\t+"} {print $1}' test.txt --> 利用正则表达式设置分隔符
4.4.3 awk 关系和布尔运算符
使用正则表达式~符号例子 # awk 'BEGIN {FS=":"} $1~/root/' /etc/passwd --> 在/etc/passwd文件中第一个域匹配root的 # awk 'BEGIN {FS=":"} $0~/root/' /etc/passwd --> 全部域匹配root的 # awk 'BEGIN {FS=":"} $0!~/nologin/' /etc/passwd --> 全部域不匹配nologin的
awk的条件语句示例 # awk 'BEGIN {FS=":"} {if($3<$4) print $0}' /etc/passwd # awk 'BEGIN {FS=":"} {if($3==10 || $4==10) print $0}' /etc/passwd # awk 'BEGIN {FS=":";count=0} {if($3>99) count++} END {print count}' /etc/passwd --> 列出系统中UID大于99的账号数量
4.4.4 表达式 + - * / %(模) ^或**(乘方) ++x x++ # awk '/^$/ {print x+=1}' input 一个计算平均值的awk脚本: Shell代码
4.4.5 awk系统变量:
另外还有个RT: RT就是当RS为正则表达式时的匹配到的每个记录的分割符的内容即为RT变量表示,用到RS的时候一般可以用RT作为每次匹配的分割符的变量的值,靠,这么解释你还不清楚就去面壁去吧。^_^ # echo "111 222a333 444b555 666"|awk 'BEGIN{RS="[a-z]+"}{print $1,RS,RT}' 当RT是利用RS匹配出来的内容。如果RS是某个固定的值时,RT就是RS的内容
示例:打印19000行至20000行 # awk '{if(NR>= 19900 && NR<=20000) print $0}' /data/log/resin/resin.log 判断log日志中通过日期的比较来打印: # awk -F, 'BEGIN{now=systime();aa=strftime("%Y-%m-%d %H:%M:%S", now)}{if ($2 > aa) print $0}' input # awk -F, 'BEGIN{now=mktime("2013 10 05 12 12 12 333");aa=strftime("%Y-%m-%d %H:%M:%S", now)}{if ($2 > aa) print $0}' input
4.4.6 格式化输出 awk使用类似于C语言的printf函数格式化输出 基本语法是:printf (格式控制符, 参数) # awk 'BEGIN {FS=","} {printf("%-15s\t%s\n",$1,$3)} ' input.txt 下面这个例子没有输入文件,直接打印一个数字,很神奇吧。 # awk 'BEGIN {printf("%-10.3f\n", 2009.12345)}'
4.4.7 内置字符串函数 字符串替换、查找、分割功能,有很多内置函数,let me see see:
解释下 gsub函数执行字符串替换功能,它将第一个字符串替换成第二个字符串。gsub函数有两种形式,第一种形式作用于全部域$0,也就是gsub(r,s)。第二种形式作用于域t,也就是gsub(r,s,t) // 第一条命令:替换第1域上的root字符串,注意我的输出的分隔符设定OFS # awk 'BEGIN {FS=":"; OFS="+"} {gsub(/root/,"haha",$1); print $0}' /etc/passwd # awk 'BEGIN {FS=":"; OFS="+"} gsub(/root/,"haha",$1) {print $0}' /etc/passwd 上面两行的席位区别,然后输出结果是:第一个命令会输出所有行,第二个只会输出gsub找到的那行,why
// index和length函数的用法 # awk 'BEGIN {print index("google.com", ".com")}' # awk 'BEGIN {print length("google.com")}'
match(s,t)测试s是否包含正则表达式t字符串,若匹配成功,则返回t的首位置,若不成功,则返回0 # awk 'BEGIN {print match("grade one", /D/)}' # awk 'BEGIN {IGNORECASE=1; print match("grade one", /D/)}'
// sub(r,s,t) 只是将t中第一次出现的r替换成s # awk 'BEGIN {str="multiprocessors program"; sub(/pro/, "PRO", str); printf("%s\n", str)}'
// substr两个函数示例: # awk 'BEGIN {str="multiprocessor programming"; print substr(str,6)}' # awk 'BEGIN {str="multiprocessor programming"; print substr(str,6,9)}'
4.4.8 向awk脚本传递参数 格式为: awk脚本文件 param1=value1 param2=value2 输入文件 其中param可以是自定义变量,也可以是系统变量 注意:命令行参数不能被BEGIN中的语句访问到
4.4.9 条件语句和循环语句 这个跟C语言语法是一样的,不多做介绍了 # if (x==y) print x # if (x ~ /[Hh]el?o) print x while(cond) action do action while(cond) for (i=0; i<10; i++) print i
4.4.10 数组 array[index]=value awk数组无需定义数组类型和大小,赋值后就能使用了,哦也。
1. 关联数组 关联数组其实就是一个Map,实际上awk数组就是一个Map,array[0]=12表示用字符串0为key,12为value awk所有数组都是关联数组,array[09]跟array[9]完全不一样 基于上述的关联数组的含义,awk定义了一组foreach循环,而且很特殊的,跟java中还不一样: for (var in array) print array[var] 实际上var就相当于Map中的key,这样可以理解了吧,^_^ 还有个条件表达式,相当于判断Map是否含有这个key值: if (index in array) print "yes"
2. split函数 终于要到压轴大戏也就是大名鼎鼎的split函数了 split(r,s,t):将字符串r以t为分隔符拆分成字符串数组,存放在s中。 并返回数组s的大小 # awk 'BEGIN {print split("abc/def/ghi",str,"/")}' # awk 'BEGIN {FS=","} {print split($1,name," ")}' input.txt 再来看一下一个小小脚本: Bash代码
3. 数组形式的系统变量 ARGV和ENVIRON两个 ARGC是ARGV数组中元素的个数 # awk -f argv.awk xyz n=99 "Hello World" 结果打印: awk,xyz,n=99,,Hello World ENVIRON变量存储了Linux系统的环境变量 例如: awk 'BEGIN {for(i in ENVIRON) print(i" = "ENVIRON[i])}'
4. awk 执行系统命令: ls -l -c --time-style="+%Y-%m-%d" | awk '{if($6 == "2013-07-01") system("rm -rf " $7)}' 不小心在当前页面新建了很多文件,怎样马上删除呢?就是上面的例子
本人博客已搬家,新地址为:http://www./ |
|
来自: 看风景D人 > 《shell脚本编程》