文本报告生成工具gawk
-----------------------------------------------------------------------------------------------------------------------------------------------
awk,文本报告生成工具,早期在unix上运行,现在linux上用的是gawk,GNU awk
基本格式awk ‘{print}’
打印第一域awk ‘{print $1}
打印第一域和第三域,中间用空格隔开awk ‘{print $1,$3}
打印第一域和第三域,中间无符号隔开awk ‘{print $1 $3}
先打印hello,再打印第一域和第三域,最后打印bye
awk ‘BEGIN{print “hello”} {print $1,$3} END{print “bye”}
awk不对文件做处理时可以用BEGIN’{……}’这种形式
内部变量引用外部变量:
对每个文件有自己的编号统计,不加F则统计到一起
awk -F 指明输入时用到的分隔符,打印时没有-F或者-v FS默认以空格为分隔符
awk -v VAR="username" -v UID="userid" '{print USER":"$1,UID":"$3}' /etc/passwd
以空格和:作为分隔符
内置变量
<1>变量:内置变量
<2>FS:输入字段分隔符,默认为空白字符
awk -v FS=':' '{print $1,FS,$3}’ /etc/passwd
awk –F: '{print $1,$3,$7}’ /etc/passwd
注:echo ‘abcd’ | awk -F "" '{print $1}',此结果$1为a,$2为b,-F “”为字符的分隔符
<3>OFS:输出字段分隔符,默认为空白字符
awk -v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’ /etc/passwd
<4>RS:输入记录分隔符,指定输入时的换行符
awk -v RS=' ' ‘{print }’ /etc/passwd
<5>ORS:输出记录分隔符,输出时用指定符号代替换行符
awk -v RS=' ' -v ORS='###'‘{print }’ /etc/passwd
<6>NF:字段数量
awk -F: ‘{print NF}’ /etc/fstab,引用内置变量不用$
awk -F: '{print $(NF-1)}' /etc/passwd
NF 表示的是浏览记录的域的个数
$NF 表示的最后一个Field(列),即输出最后一个字段的内容
<7>NR:记录号
awk '{print NR}' /etc/fstab ; awk END'{print NR}' /etc/fstab
<8>FNR:各文件分别计数,记录号
awk '{print FNR}' /etc/fstab /etc/inittab
<9>FILENAME:当前文件名
awk '{print FILENAME}’ /etc/fstab
<10>ARGC:命令行参数的个数
awk '{print ARGC}’ /etc/fstab /etc/inittab
awk ‘BEGIN {print ARGC}’ /etc/fstab /etc/inittab
<11>ARGV:数组,保存的是命令行所给定的各参数
awk ‘BEGIN {print ARGV[0]}’ /etc/fstab /etc/inittab,ARGV[0]的值是awk
awk ‘BEGIN {print ARGV[1]}’ /etc/fstab /etc/inittab
<12>自定义变量(区分字符大小写)
(1)-v var=value
(2)在program中直接定义
printf输出
<1>格式化输出:printf “FORMAT”, item1, item2, ...
(1)必须指定FORMAT
(2)不会自动换行,需要显式给出换行控制符,\n
(3)FORMAT中需要分别为后面每个item指定格式符
printf “格式符”,$1,$2,……
<2>格式符:与item一一对应
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E:显示科学计数法数值
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%: 显示%自身
<3>修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,没有小数第二个#可以不写,%3.1f,
-: 左对齐(默认右对齐) %-15s
+:显示数值的正负符号 %+d
操作符
<1>算数操作符
+、-、*、/、%
有- x:转换为负数
+X:将字符串转换为数值
<2>字符串操作符:没有符号的操作符,字符串连接
<3>赋值操作符:=,+=,-=,*=,/=,%=
<4>比较操作符:==,!=,>,>=,<,<=
<5>模式匹配符:~左边是否和右边匹配包含
!~:是否不匹配
<6>逻辑操作符:&&,||,!
<7>条件表达式(三目表达式)
注:判断$3大于1000吗?有两个变量,大于1000输入Common User,小于1000输入SysUser,右对齐15个字符串长度,usertype输出向左对齐
<8>正则表达式
<9>PATTERN:根据pattern条件,过滤匹配的行,再做处理
(1)如果未指定:空模式,匹配每一行
(2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
awk '/^UUID/{print $1}' /etc/fstab
awk '!/^UUID/{print $1}' /etc/fstab
(3) relational expression: 关系表达式,结果为“真”才会被处理
真:结果为非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
(5) BEGIN/END模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次
模式匹配,正则表达式建议还是用/,’$域 ~ /正则表达式/{print $域}’
df命令用\转义,-F” +|%”表示至少出现一个空格或者出现一次%
正则表达式
从b开头到f开头
awk控制语句
<1>{ statements;… } 组合语句
<2>if(condition) {statements;…}
<3>if(condition) {statements;…} else {statements;…}
<4>while(conditon) {statments;…}
<5>do {statements;…} while(condition):无论while条件真假,一开始do后面的执行体都会被执行一次
<6>for(expr1;expr2;expr3) {statements;…}
break
continue
delete array[index]
delete array
exit
特殊用法:能够遍历数组中的元素
语法:for(var in array) {for-body}
<7>switch语句,awk中的case循环
语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case
VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
注:default相当于shell脚本中case语句的*)
<8>break和continue
awk ‘BEGIN{sum=0;for(i=1;i<=100;i++)
{if(i%2==0)continue;sum+=i}print sum}‘
<9>awk ‘BEGIN{sum=0;for(i=1;i<=100;i++) for循环中变量表示元素的下标,非元素的值,所以想要输出元
{if(i==66)break;sum+=i}print sum}‘ 素的值,需要使用{print 数组名[变量名]}
<10>break [n]
<11>continue [n]
<12>next: 提前结束对本行处理而直接进入下一行处理(awk自身循环)
continue:结束本次循环,返回循环体
next:提前结束awk的本次内呈循环,此次不处理本行,直接进行下一行
break:结束所有循环
awk if语句
条件判断
if else写法
while循环
awk数组,键值对
<1>关联数组:array[index-expression]
<2>index-expression:
(1)可使用任意字符串;字符串要使用双引号括起来
(2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
<3>for(var in array) {for-body}
<4>注意:var会遍历array的每个索引,而不是array的值,比如说
awk 'BEGIN{weekday["mon"]="monday";weekday["tue"]="tuesday";for(I in weekday) {print i,weekday[i]}}'
i遍历的是作为weekday下标的"mon"和"tue",而不是数组weekday的值monday和Tuesday
数组举例1
awk中如果字符串或者空字符串参与运算时,也会被当做数字0,当引用一个不存在的元素时,元素会被赋值为空字符串
数组举例2,统计LISTEN和ESTABLISHED的出现次数
awk每遍历一行,就对该行最后一个字段($NF)当做索引下标来与对应的数组元素做自增操作。因为做出来的处理不能每一行都显示,只是在最后一行显示,因此在END处添加输出操作
总结:做统计时,awk每遍历一行,就对需要处理的域($0、$1、$NF)等等当做索引下标,之后让与之对应的数组元素做自增操作(即array[域]++)。因为做出来的处理不能每一行都显示,只是在最后一行显示,因此在END处添加输出操作
另:awk有一用法,awk ‘!arr[$0]++’ FILE,文件内容去重
awk函数
<1>数值处理:
rand():返回0和1之间一个随机数
awk 'BEGIN{srand(); print rand() }'
awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }':返回0和100之间一个随机整数
<2>字符串处理:
length([s]):返回指定字符串的长度,举例
sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s
echo "2008:08:08 08:08:08" | awk 'sub(/:/,“-",$1)'
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
echo "2008:08:08 08:08:08" | awk ‘gsub(/:/,“-",$0)'
gsub(/被替换的字符/,”替换的字符”,域)
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…
netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
举例说明:split(域,数组名,”分隔符”)
<3>自定义函数
<4>格式:
function name ( parameter, parameter, ... ) {
statements
return expression
}
awk中调用shell命令
<1>system命令
<2>空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。
awk BEGIN'{system("hostname") }'
awk 'BEGIN{score=100; system("echo your score is " score) }'
awk脚本
<1>将awk程序写成脚本,直接调用或执行
<2>向awk脚本传递参数
<3>格式:
awkfile var=value var2=value2... Inputfile
<4>注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v 参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数
向awk脚本传递参数
<1>格式:
awkfile var=value var2=value2... Inputfile
<2>注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v 参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数