awk操作应用

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介:

简介

   awk是数据处理工具也是报告生成工具。相比于sed常常作用于一整行的处理,awk则比较倾向于将一行分为数个字段来处理。因此,awk相当适合处理小型的数据处理。默认情况下awk将下面的变量分配给在文本行中检测到的每个数据字段:$0:表示整行文本;$1:表示文本行中的第一个数据字段;$2:表示文本行中的第二个数据字段;$n:表示文本行中的第n个数据字段。

awk用法格式是:awk [options]‘模式类型1{动作1}’FILE1...

常用选项

选项

描述

-F FS

指定描述一行中的数据字段的文件分隔符

-f awk_script

指定读取程序的文件名,可指定载入脚本

-v VAR_VALUE

定义awk程序中使用的变量和默认值

模式类型

空模式:没有指定任何模式,遍历文件中的每一行

1
2
3
4
5
6
[root@zhao ~] # awk -F: '{print $1,$7}' /etc/passwd
root  /bin/bash
bin  /sbin/nologin
daemon  /sbin/nologin
adm  /sbin/nologin
lp  /sbin/nologin

BEGIN模式:在执行所有awk脚本动作之前执行的预设类(准备)的工作

1
2
3
4
5
6
7
[root@zhao ~] # awk -F: 'BEGIN {print "USERNAME  SHELL"}{print $1,$7}' /etc/passwd
USERNAME  SHELL                #使用BEGIN模式设定的预设字符
root  /bin/bash
bin  /sbin/nologin
daemon  /sbin/nologin
adm  /sbin/nologin
lp  /sbin/nologin

小拓展分隔符包含字段分隔符(默认为空白符)和行分隔符(默认为换行符)其中使用FS:指定输入分隔符也是awk的内置变量;OFS指定输出分隔符;NF指定最后一个字段。

   FS指定输入分隔符

1
2
3
4
5
6
[root@zhao ~] # awk  'BEGIN {FS=":"}{print $1,$7}' /etc/passwd
root  /bin/bash
bin  /sbin/nologin
daemon  /sbin/nologin
adm  /sbin/nologin
lp  /sbin/nologin

   OFS指定输出分隔符

1
2
3
4
5
6
[root@zhao ~] # awk  'BEGIN {FS=":";OFS="*********"}{print $1,$7}' /etc/passwd
root********* /bin/bash
bin********* /sbin/nologin
daemon********* /sbin/nologin
adm********* /sbin/nologin
lp********* /sbin/nologin

   NF指定最后一个字段

1
2
3
4
5
6
[root@zhao ~] # df -lh | awk '!/^File/{printf"%-25s %s\n",$1,$NF}'
/dev/mapper/vg0-root       /
tmpfs                      /dev/shm
/dev/sda1                  /boot
/dev/mapper/vg0-usr        /usr
/dev/mapper/vg0-var        /var

END模式:在awk脚本动作执行完成之后做的简单的收尾操作,主要用于统计使用

1
2
3
4
5
6
7
8
[root@zhao ~] # awk  'BEGIN {FS=":";OFS="***";print "USERNAME   SHELL"}{print $1,$7}END {print "********END******"}' /etc/passwd
USERNAME   SHELL
root*** /bin/bash
bin*** /sbin/nologin
daemon*** /sbin/nologin
sshd*** /sbin/nologin
tcpdump*** /sbin/nologin
********END******

正则表达式:(格式:/PATTERN/)表示对于被正则表达式匹配到的行进行操作,而并非所有行

1
2
3
4
5
6
7
[root@zhao ~] # awk -F: '/in$/{print $1,$7}' /etc/passwd
bin  /sbin/nologin
daemon  /sbin/nologin
adm  /sbin/nologin
lp  /sbin/nologin
mail  /sbin/nologin
uucp  /sbin/nologin

表达式:其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu"

   支持使用~(匹配)和!~(不匹配),>=,<=,>,< 等所有比较操作符

1
2
3
4
5
6
7
[root@zhao ~] # awk -F: '$3>=50{print $1,$3}' /etc/passwd
nobody 99
dbus 81
usbmuxd 113
vcsa 69
rtkit 499
avahi-autoipd 170

   支持逻辑关系操作符

1
2
3
[root@zhao ~] # awk -F: '$3>=500 && $7~/bash/{printf "%-15s %i %s\n",$1,$3,$7}' /etc/passwd
user1           500  /bin/bash
user2           501  /bin/bash

指定匹配范围,格式为pat1,pat2

这个匹配模式类型很难理解,我们用一个例题来解析:

  eg:匹配一个文件中以abc开头aaa结尾的字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[root@zhao ~] # awk '/abc/,/aaa/{print $0}' awk.sh
abc 3          #开始
cde 4
aaa 5          #结束
abc 6          #开始
aab 7
axd 8
hell0 9
aaa 10         #结束
abc how are you aaa      #开始结束
abc 12          #开始
sss
ddd
sxd
xvf            #无结尾字段会直接遍历到文件尾部

输出动作介绍

 1、print

   print的使用格式:print item1, item2, ...

   要点:

     (1)、各项目之间使用逗号隔开,而输出时则以空白字符分隔;

     (2)、输出的item可以为字符串或数值、当前记录的字段(如$1)、变量或awk的表达式;数值会先转换为字符串,而后再输出;

     (3)、print命令后面的item可以省略,此时其功能相当于print $0, 因此,如果想输出空白行,则需要使用print"";


2、printf

    printf命令的使用格式:printf format, item1, item2,...

    要点:

      (1)、其与print命令的最大不同是,printf需要指定format;

      (2)、format用于指定后面的每个item的输出格式;

      (3)、printf语句不会自动打印换行符;\n

      其中format格式的指示符都以%开头,后跟一个字符;如下:

      %c: 显示字符的ASCII码;

      %d, %i:十进制整数;

      %e, %E:科学计数法显示数值;

      %f: 显示浮点数;

      %g, %G: 以科学计数法的格式或浮点数的格式显示数值;

      %s: 显示字符串;

      %u: 无符号整数;

      %%: 显示%自身;


    在输出格式上常用修饰符:

       N: 显示宽度;

       -: 左对齐(默认为右对齐);

       +:显示数值符号;

eg

1
2
3
4
5
6
7
[root@zhao ~] # awk -F: '{printf "%-15s %i\n",$1,$3}' /etc/passwd
root            0
bin             1
daemon         2
adm            3
lp              4
sync             5

控制语句的使用

常见类型:if;while; for; case; do...while; break; continue; next

(1)、if-else

   语法:if (condition){then-body} else {[else-body]}

   解析:condition是判断条件通常为布尔表达式或逻辑表达式

1
2
3
4
5
6
7
8
[root@zhao ~] # awk -F: '{if ($3==0) {print $1, "Adminitrator";} else { print $1,"Common User"}}' /etc/passwd
root Adminitrator
bin Common User
daemon Common User
adm Common User
lp Common User
sync  Common User
shutdown  Common User
1
2
[root@zhao ~]# awk -F: -v sum= 0  '{if ($3>=500) sum++}END{print sum}'  /etc/passwd
3                #所有UID大于 500 的用户个数


(2)、while

   首先说明在awk中的循环不是循环每一行的而是循环切片之后的每一个字段的

   语法: while(condition){statement1; statment2; ...}

1
2
3
4
5
6
7
[root@zhao ~] # awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwd
root            #i=1时输出第一个字段
x               #i=2时输出第二个字段
0               #i=3时输出第三个字段
bin             #第二行...
x
1
1
2
3
4
5
6
[root@zhao ~] # awk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {printf "%s ", $i}; i++ ;};printf "\n"}' /etc/passwd
root root  /root  /bin/bash
/bin  /sbin/nologin
daemon daemon  /sbin  /sbin/nologin
/var/adm  /sbin/nologin
/var/spool/lpd  /sbin/nologin

解析:length是awk的内置函数,获取字段的长度的;而这里length($i)指的是$i字段的长度。


(3)、do-while

   和while循环的区别:while循环是当条件不满足时不会执行任何循环操作,而do-while是不论条件真假与否首先执行一次循环体,然后再去判断条件满足与否,满足继续执行不满足不再执行。也就是说不管条件满足与否,至少执行一次循环体。

   语法: do{statement1, statement2, ...} while (condition)

1
2
3
4
5
6
[root@zhao ~] # awk -F: '{i=4;do {print $i;i--}while(i>4)}' /etc/passwd
0
1
2
4
7

解析:此命令中的while循环并不成立但是还是执行了print$4这就是do-while的体系结构若还不太明白可对比使用:[root@zhao ~]# awk -F: '{i=4;while (i>4){print $i;i--}}'/etc/passwd此命令执行之后不会有任何执行结果。


(4)、for

   语法: for ( 初始赋值; condition(变量条件);修正变量(初始值)) { statement1, statement2, ...}

1
2
3
4
5
6
7
8
[root@zhao ~] # awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
root
x
0
bin
x
1
daemon


(5)、case

  语法:switch(expression) { case VALUE or /REGEXP/: statement1, statement2,... default:statement1, ...}

 由于此语句不常使用所以不做深入研究,有意学习者请参考其他文章


(6)、break 和 continue

  常用于循环或case语句中,具体使用方法和bash中基本类似,所以此处不做重点阐述


(7)、next

  这个为awk的独有命令,表示提前结束对本行文本的处理,并接着处理下一行;

  例如,显示其ID号为奇数的用户:

1
2
3
4
5
6
7
8
[root@zhao ~] # awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
bin 1
adm 3
sync  5
halt 7
operator 11
gopher 13
nobody 99


(8)、数组应用

   数组:一组连续的可存储多个值内存空间,可使用数组索引(下标)来引用数组。

   语法:array[index-expression]

     index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。


若遍历数组中的每一个元素,需要使用如下的特殊结构:

语法:for (var in array) {statement1, ... }

其中,var用于引用数组下标,而不是元素值;

1
2
3
4
5
6
[root@zhao ~] # awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd
  /sbin/shutdown :1
       /bin/bash :3
   /sbin/nologin :31
      /sbin/halt :1
       /bin/sync :1

解析:$NF为最后一个字段,^$表示为空,BASH[$NF]表示下标为$NF数组,也就是说可能出现BASH[/bin/bash]等

awk的内置函数使用与介绍

  • split(string, array[, fieldsep [, seps ] ])

  解析:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;

1
2
3
4
[root@zhao ~] # netstat -tan | awk '/:80\>/{split($5,clients,":");ip[clients[4]]++}END{for(a in ip) print ip[a],a}' | sort -rn | head -50
100 172.16.18.11
1 *
##########此命令在不开启IPv6的centos6.4上执行的###########

例题解析:split($5,clients,":")是使用冒号分割将第5段保存到clients数组中;IP[clients[1]]++}提取第一部分(IP地址)保存到IP这个变量中;{for(iin IP){print IP[i],i}}遍历IP地址并显示次数和IP地址;sort -rn 根据次数进行逆向排序,head -5O只取前50个。

  例:取出当前使用比例已经大于20%的文件系统

1
2
[root@zhao ~] # df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]>=20){print $1}}'
/dev/mapper/vg0-usr


  • length([string])

   解析:返回string字符串中字符的个数;


  • substr(string, start[, length])

   解析:取string字符串中的子串,从start开始,取length个;start从1开始计数;


  • system(command)

   解析:执行系统command并将结果返回至awk命令


  • systime()

  解析:取系统当前时间


  • tolower(s)

  解析:将s中的所有字母转为小写


  • toupper(s)

  解析:将s中的所有字母转为大写


       至此awk的应用知识基本阐述完毕,如有错误或无阐述到位的问题请留言注明,大家的支持是我学习路上前进的动力!!



本文转自 z永 51CTO博客,原文链接:http://blog.51cto.com/pangge/1286728


相关文章
|
7月前
|
数据处理 Perl
AWK 命令20条
AWK 命令示例:显示文件内容、按列打印、计数、使用分隔符、模式匹配、条件语句、数学计算、数组操作、字符串处理、循环、输出格式控制、删除重复行、统计行词字符、分组统计、格式化输出、字段联合、自定义分隔符、字符串截取和调用外部命令。AWK 是强大的文本分析工具,适用于各种数据处理任务。
125 1
|
7月前
|
Perl
awk中的模式范围
awk中的模式范围
58 3
|
7月前
|
Perl
awk范围模式
awk范围模式
89 4
|
7月前
|
Perl
awk的复杂用法
awk的复杂用法
84 3
|
7月前
|
Perl
awk的具体用法
awk的具体用法
93 1
|
Shell Linux Perl
|
Shell Docker Perl