Linux学习第二十二节课-awk

                                                          Linux学习第二十二节课

-----------------------------------------------------------------------------------------------------------------------------------------------

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’{……}’这种形式

内部变量引用外部变量:

image.png

对每个文件有自己的编号统计,不加F则统计到一起

image.png

awk -F 指明输入时用到的分隔符,打印时没有-F或者-v FS默认以空格为分隔符

awk -v VAR="username" -v UID="userid" '{print USER":"$1,UID":"$3}' /etc/passwd

以空格和:作为分隔符

image.png

内置变量

<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:无符号整数

       %%: 显示%自身

image.png

<3>修饰符:

       #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,没有小数第二个#可以不写,%3.1f,

       -: 左对齐(默认右对齐) %-15s

       +:显示数值的正负符号 %+d

操作符

<1>算数操作符

       +、-、*、/、%

       有- x:转换为负数

       +X:将字符串转换为数值

<2>字符串操作符:没有符号的操作符,字符串连接

<3>赋值操作符:=,+=,-=,*=,/=,%=

<4>比较操作符:==,!=,>,>=,<,<=

<5>模式匹配符:~左边是否和右边匹配包含

                     !~:是否不匹配

<6>逻辑操作符:&&,||,!

<7>条件表达式(三目表达式)

image.png

注:判断$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 $域}’

image.png

image.png

df命令用\转义,-F” +|%”表示至少出现一个空格或者出现一次%

image.png

正则表达式

image.png

从b开头到f开头

image.png


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语句

条件判断

image.png

if else写法

image.png

while循环

image.png

image.png 


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

image.png


数组举例1

image.png

awk中如果字符串或者空字符串参与运算时,也会被当做数字0,当引用一个不存在的元素时,元素会被赋值为空字符串

数组举例2,统计LISTEN和ESTABLISHED的出现次数

awk每遍历一行,就对该行最后一个字段($NF)当做索引下标来与对应的数组元素做自增操作。因为做出来的处理不能每一行都显示,只是在最后一行显示,因此在END处添加输出操作

image.png

总结:做统计时,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]):返回指定字符串的长度,举例

image.png

       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(域,数组名,”分隔符”)

image.png

<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参数


猜你喜欢

转载自blog.51cto.com/13873498/2173732