awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk是 AWK的 GNU版本。
awk其名称得自于它的创始人 Alfred Aho、Peter Weinberger和 Brian Kernighan姓氏的首个字母。实际上 AWK的确拥有自己的语言: AWK程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报 表,还有无数其他的功能。
awk工作流程是这样的:读入有'/n'换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域,$0则表示所有域,$1表示第一个域,$n表示第n个域。默认域分隔符是"空白键"或 "[tab]键"
最重要的是awk还是一门编程语言,后边详细总结。
awk '{pattern + action}' {filenames}
尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。pattern就是要表示的正则表达式,用斜杠括起来。
awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。
通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。
有三种方式调用awk
1.命令行方式awk [-F field-separator] 'commands' input-file(s)
其中,commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。
2.shell脚本方式
将所有的awk命令插入一个文件,并使awk程序可执行,然后awk命令解释器作为脚本的首行,一遍通过键入脚本名称来调用。
相当于shell脚本首行的:#!/bin/sh
可以换成:#!/bin/awk
3.将所有的awk命令插入一个单独文件,然后调用:awk -fawk-script-file input-file(s)
其中,-f选项加载awk-script-file中的awk脚本,input-file(s)跟上面的是一样的。
last -n 5 | awk '{PRint $1}' 列出最后登录系统的5人的名字
cat /etc/passwd | awk -F ':' '{print $1}' 列出系统上所有用户
cat /etc/passwd | awk -F ':' '{print $1 "/t"$7}' 显示用户名和所对应的shell
cat /etc/passwd |awk -F ':' 'BEGIN {print "name,shell"} {print $1","$7} END{print "blue,/bin/nosh"}'
awk -F : '/root/' /etc/passwd
awk -F : '/^root/' /etc/passwd
printf使用实例,打印的好看点。printf命令的使用格式:printf format, item1, item2, ...要点:1、其与print命令的最大不同是,printf需要指定format;2、format用于指定后面的每个item的输出格式;3、printf语句不会自动打印换行符;/nformat格式的指示符都以%开头,后跟一个字符;如下:%c: 显示字符的ASCII码;%d, %i:十进制整数;%e, %E:科学计数法显示数值;%f: 显示浮点数;%g, %G: 以科学计数法的格式或浮点数的格式显示数值;%s: 显示字符串;%u: 无符号整数;%%: 显示%自身;修饰符:N: 显示宽度;-: 左对齐;+:显示数值符号;例子:# awk -F: '{printf "%-15s %i/n",$1,$3}' /etc/passwd
cat /etc/passwd | awk -F ':' 'BEGIN{printf "%-15s%-15s/n", "name","shell"}{printf "%-15s%-15s/n", $1,$7} END{printf "%-15s%-15s/n","blue","/bin/nobash"} '
输出重定向print items > output-fileprint items >> output-fileprint items | command特殊文件描述符:/dev/stdin:标准输入/dev/sdtout: 标准输出/dev/stderr: 错误输出/dev/fd/N: 某特定文件描述符,如/dev/stdin就相当于/dev/fd/0;例子:# awk -F: '{printf "%-15s %i/n",$1,$3 > "/dev/stderr" }' /etc/passwd
1.1 awk内置变量之记录变量:FS: field separator,读取文件本时,所使用字段分隔符;RS: Record separator,输入文本信息所使用的换行符;OFS: Output Filed Separator: ORS:Output Row Separator:awk -F:OFS="#"FS=":"1.2 awk内置变量之数据变量:NR: The number of input records,awk命令所处理的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;NF:Number of Field,当前记录的field个数;FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;ARGC: awk命令的参数的个数;FILENAME: awk命令所处理的文件的名称;ENVIRON:当前shell环境变量及其值的关联数组;如:awk 'BEGIN{print ENVIRON["PATH"]}'
awk -F ':' '{print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd
awk '{FS="#";print "filename:" FILENAME ",linenumber:" NR ",columns:" NF ",linecontent:"$0}' /etc/passwd 注意观察columns
1.3 用户自定义变量gawk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头。gawk变量名称区分字符大小写。
在脚本中赋值变量在gawk中给变量赋值使用赋值语句进行,例如:awk 'BEGIN{var="variable testing";print var}'在命令行中使用赋值变量gawk命令也可以在“脚本”外为变量赋值,并在脚本中进行引用。例如,上述的例子还可以改写为:awk -v var="variable testing" 'BEGIN{print var}'
awk的操作符:1>算术操作符:-x: 负值+x: 转换为数值;x^y: x**y: 次方x*y: 乘法x/y:除法x+y:x-y:x%y:
例:awk 'BEGIN{A=3; B=4;print A+B}'
2>赋值操作符:=+=-=*=/=%=^=**=++--需要注意的是,如果某模式为=号,此时使用/=/可能会有语法错误,应以/[=]/替代;例:awk 'BEGIN{A=3; B=4;print A+=4}'
3>比较操作符:x < y True if x is less than y. x <= y True if x is less than or equal to y. x > y True if x is greater than y. x >= y True if x is greater than or equal to y. x == y True if x is equal to y. x != y True if x is not equal to y. x ~ y True if the string x matches the regexp denoted by y. x !~ y True if the string x does not match the regexp denoted by y. subscript in array True if the array array has an element with the subscript subscript.
例:awk 'BEGIN{A=3; B=4;if(A>B){print "yes";print"shi"}else {print "no"}}'
awk 'BEGIN{A="root"; B="r.t";if(A~B){print "yes";print"shi"}else {print "no"}}' B变量是一个正则表达式
4>条件表达式:
例:awk 'BEGIN{A=3; B=4;if(A>B){print "yes";print"shi"}else {print "no"}}'
表达式间的逻辑关系符:&&||
例:awk 'BEGIN{A=3; B=4;if(A<B && A-1<B){print "yes";print"shi"}else {print "no"}}'
5>函数:
自定义函数和调用
awk 'function test(a,b){return a>b;} BEGIN{ if(test(4,3)){print "yes";print"shi"}else {print "no"}}'
内置函数调用
awk的内置函数split(string, array [, fieldsep [, seps ] ])功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从0开始的序列;netstat -ant | awk '/:80/>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50 自己运行查看下数组元素倒叙的length([string])功能:返回string字符串中字符的个数;substr(string, start [, length])功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;system(command)功能:执行系统command并将结果返回至awk命令systime()功能:取系统当前时间tolower(s)功能:将s中的所有字母转为小写toupper(s)功能:将s中的所有字母转为大写
6>循环语句:
for循环:语法: for ( variable assignment; condition; iteration process) { statement1, statement2, ...}awk -F: '{for(i=1;i<=3;i++) print $i}' /etc/passwd
awk -F: '{for(i=1;i<=NF;i++) { if (length($i)>=4) {print $i}}}' /etc/passwd NF是字段数量,length是内置的函数
while语法: while (condition){statement1; statment2; ...}awk -F: '{i=1;while (i<=3) {print $i;i++}}' /etc/passwdawk -F: '{i=1;while (i<=NF) { if (length($i)>=4) {print $i}; i++ }}' /etc/passwd
do-while循环:语法: do {statement1, statement2, ...} while (condition)awk -F: '{i=1;do {print $i;i++}while(i<=3)}' /etc/passwd
case 语句:不是所有awk都支持语法:switch (expression) { case VALUE or /REGEXP/: statement1, statement2,... default: statement1, ...}
break 和 continue常用于循环或case语句中
例: awk 'BEGIN{i=1;while (i<=3) {if(i==2){i++;continue};print i;i++}}'
next提前结束对本行文本的处理,并接着处理下一行;例如,下面的命令将显示其ID号为奇数的用户:# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
7>awk中使用数组
array[index-expression]index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。要遍历数组中的每一个元素,需要使用如下的特殊结构:for (var in array) { statement1, ... }其中,var用于引用数组下标,而不是元素值;
例子: awk 'BEGIN{A[0]="a";A[1]="b";A[2]="c"; for(i in A){ print i,A[i]} }'
删除数组变量从关系数组中删除数组索引需要使用delete命令。使用格式为:delete array[index]
例:awk 'BEGIN{A[0]="a";A[1]="b";A[2]="c"; delete A[1]; for(i in A){ print i,A[i]} }'
新闻热点
疑难解答