描述awk命令和函数的用法及示例

2018-05-26  本文已影响0人  华龙007

一、简介

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

二、命令的用法

命令格式

gawk [options] 'program...' FILE ...

常见选项

-F fs:指明字段分隔符;
-v var=value:自定义变量;

program语句

常见格式:PATTERN{ACTION STATEMENTS} #语句之间用分号分隔

  1. print
  1. 变量
  1. printf命令
  1. 操作符
    算术操作符: x+y, x-y, x*y, x/y, x^y, x%y,-x,+x
    字符串操作符:没有符号的操作符,字符串连接
    赋值操作符:=, +=, -=, *=, /=, %=, ^=, ++, --
    比较操作符:>, >=, <, <=, !=, ==
    模式匹配符::是否匹配,!:是否不匹配
    逻辑操作符:&&,||,!
    函数调用:function_name(argu1, argu2, ...)
    条件表达式:selector?if-true-expression:if-false-expression

  2. PATTERN
    (1) empty:空模式,匹配每一行;
    (2) /regular expression/:仅处理能够被此处的模式匹配到的行;
    (3) relational expression: 结果为真才会被处理;真为非0值,非空字符串;
    (4) line ranges:行范围,startline,endline:/pat1/,/pat2/
    注意: 不支持直接给出数字的格式
    ~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
    (5) BEGIN/END模式
    BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
    END{}:仅在文本处理完成之后执行一次;

  3. 常用的action
    (1) Expressions
    (2) Control statements:if, while等;
    (3) Compound statements:组合语句;
    (4) input statements
    (5) output statements

  4. 控制语句

关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
weekdays[mon]="Monday"
若要遍历数组中的每个元素,要使用for循环;
for(var in array) {for-body}
~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
注意:var会遍历array的每个索引;
如果数组不存在,我们引用数组,会创建,值为空,引用数组的值为0。

1.内置函数
数值处理:
rand():返回0和1之间一个随机数
字符串处理:
length([s]):返回指定字符串的长度;
sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;t中有没有r,有替换成s
gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中;
~]# netstat -tan | awk '/^tcp>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'

2.自定义函数

三、入门实例

1.把文本分片后排列整齐,并加上标签
[root@localhost sctript]# cat awk01 
 Mike Harrington:(510) 548-1278:250:100:175
 Christian Dobbins:(408) 538-2358:155:90:201
 Susan Dalsass:(206) 654-6279:250:60:50
 Archie McNichol:(206) 548-1348:250:100:175
 Jody Savage:(206) 548-1278:15:188:150
 Guy Quigley:(916) 343-6410:250:100:175
 Dan Savage:(406) 298-7744:450:300:275
 Nancy McNeil:(206) 548-1278:250:80:75
 John Goldenrod:(916) 348-4278:250:100:175
 Chet Main:(510) 548-5258:50:95:135
 Tom Savage:(408) 926-3456:250:168:200
 Elizabeth Stachelin:(916) 440-1763:175:75:300
[root@localhost sctript]# awk -F: 'BEGIN{printf "%-20s %-15s %-4s %-4s %-4s\n","Name","PHone","Jan","Feb","MAR"}BEGIN{print"--------------------------------------------------"}{printf "%-20s %-15s %-4s %-4s %-4s\n",$1,$2,$3,$4,$5}' awk01
Name                 PHone           Jan  Feb  MAR 
--------------------------------------------------
 Mike Harrington     (510) 548-1278  250  100  175 
 Christian Dobbins   (408) 538-2358  155  90   201 
 Susan Dalsass       (206) 654-6279  250  60   50  
 Archie McNichol     (206) 548-1348  250  100  175 
 Jody Savage         (206) 548-1278  15   188  150 
 Guy Quigley         (916) 343-6410  250  100  175 
 Dan Savage          (406) 298-7744  450  300  275 
 Nancy McNeil        (206) 548-1278  250  80   75  
 John Goldenrod      (916) 348-4278  250  100  175 
 Chet Main           (510) 548-5258  50   95   135 
 Tom Savage          (408) 926-3456  250  168  200 
 Elizabeth Stachelin (916) 440-1763  175  75   300 
2.删除行内与第一列字符相同的字符
[root@localhost sctript]# cat c
a b c a d a
s d d d x s a
h j s a s h j h
j d f j a s j k j
[root@localhost sctript]# awk '{a=$1;gsub(" ?"a,"");print a""$0}' c
a b c d
s d d d x a
h j s a s j
j d f a s k

a=$1把第一列赋值变量a。
gsub(" ?"a,"")用函数gsub进行行内全局替换," ?"a是正则,表示前面的空格可以没有也可以有一次,把匹配到的全部替换成空格。
print a""$0打印,在行首添加上变量a,也就字段$1。

3.打印学生的平均成绩
[root@localhost sctript]# cat d
Sophia huaxue 90
Faye   huaxue 80
Sophia wuli   70
Faye   wuli   60
[root@localhost sctript]# awk '{b[$1]=$1} {a[$1]++;c[$1]+=$3} END {for(i in b);for(i in a);for(i in c){y=c[i]/a[i];printf("%-8s平均成绩为:\t%2.2f\n",b[i],y)}}' d
Sophia  平均成绩为:  80.00
Faye    平均成绩为:  70.00

分析分两步:
1.先打印名字
awk '{b[$1]=$1}END{for(i in b)print b[i]}' d
Sophia
Faye
{b[$1]=$1}以名字为变量b的下标,并在里面赋值名字。
END{for(i in b)print b[i]}在最后,遍历数组b,并打印每一个元素。

2.打印平均分数
]# awk '{a[$1]++;c[$1]+=$3}END{for(i in a){y=c[i]/a[i];print y}}' d
80
70
{a[$1]++;c[$1]+=$3}以名字为变量a的下标,自增计数。以名字为变量c的下标,拿自己和$3分数的相加在赋值给自己。
{y=c[i]/a[i];print y}总分除以计数的到平均分

把两个整合awk '{b[$1]=$1} {a[$1]++;c[$1]+=$3} END {for(i in b);for(i in a);for(i in c){y=c[i]/a[i];printf("%-8s平均成绩为:\t%2.2f\n",b[i],y)}}' d

4.文本a记录姓名、学号,文本b记录学号、学科、成绩。把a和b组合成一张表格。
[root@localhost sctript]# cat a
Sophia|0001
Faye|0002

[root@localhost sctript]# cat b
0001|Chinese|77
0001|Music|90
0002|Chinese|62
0002|Music|80
[root@localhost sctript]# awk -F \| 'NR==FNR{a[$2]=$1;next}{printf "%-8s %-6s %-8s %-2s\n",a[$1],$1,$2,$3}' a b
Sophia   0001   Chinese  77
Sophia   0001   Music    90
Faye     0002   Chinese  62
Faye     0002   Music    80

NR表示a数据和b数据的总行数,FNR表示a和b分别计数
NR==FNR为真时表示读入的是a数据,执行之后的代码a[$2]=$1;next
a[$2]=$1;next表示把a文件切片的字段1放入数组a,数组a下标用字段2的值
NR==FNR为假时表示读入的是b数据,执行printf中的代码

printf "%-8s %-6s %-8s %-2s\n",a[$1],$1,$2,$3格式化输出b文件切片后的值
a[$1],$1,$2,$3,其中第一个a[$1]是读取a文件时新建的数组a,这是个关联数组,文件a中$2的值等于文件b中$1的值,所以就可以把文件a存入数组的值和文件b的各字段数值一起打印出来。

5.把文本分片后按字母顺序输出相同两个字符的字段
[root@localhost sctript]# cat sting 
asf|zz|123|bb|q23|cc|py|dd|ab|ee|x6|ff|ffq|gg|aaa|hh|aa
[root@localhost sctript]# awk -F \| '{for(i=1;i<=NF;i++){if($i~/^([a-z]){2}$/) {a=substr($i,1,1);b=substr($i,2,2);if(a==b) print $i | "sort"}}}' sting 
aa
bb
cc
dd
ee
ff
gg
hh
zz

文本切割后按照字段个数挨个循环,用模式匹配出只有2个字母的字段,对这个字段的两个字母对比,相等时打印并传递到sort命令中排序。

6.把grades中每行的字段分别从小到大排序
[root@localhost sctript]# cat grades 
44 55 66 22 77 99
100 22 77 99 33 66
55 66 100 99 88 45
[root@localhost sctript]# vim sorter.awk 
#!/bin/awk -f
#这里我用选择排序算法进行排序
{for(i=0;i<NF;i++){array[i]=$(i+1)}}
sort(array)

function sort (temp){
        for(i=0;i<length(temp)-1;i++){
                min=i
                for(j=i+1;j<length(temp);j++){
                        if(temp[min]>temp[j]){
                                min=j
                        }
                }
                if(min!=i){
                        temp1=temp[i]
                        temp[i]=temp[min]
                        temp[min]=temp1
                }
        }
        for(i=0;i<NF;i++){
                printf("%d ", temp[i])
        }
        printf "\n"
}
[root@localhost sctript]# ./sorter.awk grades
22 44 55 66 77 99 
22 33 66 77 99 100 
45 55 66 88 99 100
上一篇下一篇

猜你喜欢

热点阅读