awk简介
awk是一款文本处理工具,awk为文本处理提供了非常强大的功能,包括正则表达式的匹配,样式装入,程序的流程控制,数学运算,还包括了内置函数和变量。它完全可以作为一门独立的语言进行编程。
基本语法:
awk [options] ‘pattern{ action }‘ file file ...
awk对文本的处理是以行为单位的,按行读取数据后再对每个字段进行处理。
awk的大致工作流程如下:
1)首先读入第一行,然后将每个字段进行切割并赋值给$0,$1,$2,$3.....(默认分隔符为[tab]键或空格键)
2)判断该行是否和pattern(模式)相匹配,若匹配则执行后面的action(动作),若不匹配,继续下一行的处理。
3)读入下一行,重复前两个步骤,直到遍历完所有的行。
awk的变量
1)内置变量
awk有很多的内置变量,以便在pattern、action中可以直接引用。
(1)$0,$1,$2,$3.... #每一行的第一个字段($1),第二个字段($2),$0表示整行数据
(2)FS:Field Seperator #输入时的字段分隔符
例如:对passwd文件使用“:”作为字段分隔符,然后输出第一个字段(用户),输入分隔符也可以在选项中通过“-F”指定,效果一样。(BEGIN为模式的一种,仅在数据读入之前执行一次,往往在BEGIN中对内置变量进行赋值)
[root@www ~]# awk ‘BEGIN{FS=":"}{print $1}‘ /etc/passwd root bin daemon .....
(3)RS:Record Seperator #输入行分隔符(换行符)
例如:在passwd文件读入之前指定“:”为行分隔符,则由“:”分隔的每一个字段单独为一行
[root@www ~]# awk ‘BEGIN{RS=":"}{print $0}‘ /etc/passwd root x 0 0 root /root /bin/bash ........
(4)OFS:Output Field Seperator #输出时的字段分隔符;
想要让OFS生效首先要对字段进行分隔,这儿的输出时字段分隔符指的是print后面每个字段之间的($1和$7之间的分隔符)
[root@www ~]# awk ‘BEGIN{FS=":";OFS="#0.0#"}{print $1,$7}‘ /etc/passwd root#0.0#/bin/bash bin#0.0#/sbin/nologin daemon#0.0#/sbin/nologin .......
(5)ORS:Outpput Row Seperator #输出时的行分隔符;
默认的行分隔符是“\n“,如果替换成别的别的符号(#),原本换行的地方都替换成了#。
[root@www ~]# awk -F: ‘BEGIN{ORS="####"}{print $1,$7}‘ /etc/passwd root /bin/bash####bin /sbin/nologin####daemon /sbin/nologin####adm /sbin/nologin####lp /sbin/nologin####......
(6)NF:Numbers of Field #每一行字段数
这个取决于使用的分隔符
[root@www ~]# awk ‘BEGIN{FS=":"}{print $1,NF}‘ /etc/passwd root 7 bin 7 daemon 7
(7)NR:Numbers of Record #行数,当前正在处理的行,所有文件一并计数
(8)FNR #行数;各文件分别计数
当awk对多个文件进行处理时,FNR是对每个文件单独计数,而NR是所有的文件一并计数,当处理完第一个文件开始处理第二个文件时,NR继续累加,而不会从1重新开始计数。如下图,abc文件有3行,def文件有4行......
(9)ARGV #数组,保存命令本身和后面的参数
[root@www tmp]# awk ‘BEGIN{print ARGV[0],ARGV[1],ARGV[2],ARGV[3]}‘ a b c awk a b c
(10)ARGC #保存awk命令中参数的个数;
(11)FILENAME #awk正在处理的当前文件的名称;
2)自定义变量
自定义变量的定义方式有两种:
(1)在options(选项)中通过”-v“定义
(2)直接在pattern或action中进行定义
通过-v定义:
[root@www tmp]# awk -v name=root ‘BEGIN{print name}‘ root
在pattern或action中定义(注意:若action中存在多个语句需要用”;“隔开)
[root@www tmp]# awk ‘BEGIN{a=2;print a}‘ 2 [root@www tmp]# awk -F: ‘a=$1{print a}‘ /etc/passwd root bin daemon .........
awk的操作符
awk中的操作符和C语言中的非常相似。简单介绍一下,算术运算符包括:x+y,x-y,x*y,x/y,x**y(即x^y),x%y(取模),-x,+x。赋值运算符包括:=,+=,-=,*=,/=,%=,*=,**=,++(自加),--(自减).......。比较运算符包括:,<,<=,>,>=,==,!=,~(模式匹配,左边的字符串能够被右边的模式匹配为真),!~(与前者相反)....。逻辑运算符:&&(与运算),||(或运算)。
条件表达式:
格式:selector?if-true-expression:if-false-expression
[root@www tmp]# awk -F: ‘{$3>=500?user="common user":user="admin or system user";print $1,"is",user}‘ /etc/passwd root is admin or system user bin is admin or system user daemon is admin or system user .......
pattern
pattern也可以理解成条件,awk读入一行数据后,会先判断是否符合条件,若符合则执行该条件后面的action,若不符合去匹配下一个pattern(若有多个pattern的话)或读入下一行。awk允许有多个pattern存在,符合哪一个pattern即执行后面的action:
awk [options] ‘pattern{ action }pattern{ action }‘ file file ...
例如:
[root@www tmp]# awk -F: ‘$3<1{print $1,"admin"}$3>500{print $1,"common user"}‘ /etc/passwd root admin nfsnobody common user
pattern(模式)的类型:
(1)Regexp #正则表达式,格式为/PATTERN/
[root@www tmp]# awk -F: ‘/baby/{print}‘ /etc/passwd baby:x:500:500::/home/baby:/bin/bash
(2)Expression #表达式,其结果为非0或非空字符串时满足条件;
[root@www tmp]# awk -F: ‘$3>=500{print}‘ /etc/passwd nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin baby:x:500:500::/home/baby:/bin/bash
(3)Ranges #行范围,格式:startline, endline
startline, endline有两种形式:正则表达式(/regexp1/,/regexp2/{action}),regexp1匹配的行至regexp2匹配的行,对中间所有的行进行处理;NR指定特定行(NR==1,NR==5{action}),对1~5行进行处理。
正则表达式:
[root@www tmp]# awk -F: ‘/sync/,/uucp/{print NR,$1,$7}‘ /etc/passwd 6 sync /bin/sync 7 shutdown /sbin/shutdown 8 halt /sbin/halt 9 mail /sbin/nologin 10 uucp /sbin/nologin
NR指定特定行:
[root@www tmp]# awk -F: ‘NR==1,NR==5{print NR,$1,$7}‘ /etc/passwd 1 root /bin/bash 2 bin /sbin/nologin 3 daemon /sbin/nologin 4 adm /sbin/nologin 5 lp /sbin/nologin
(4)BEGIN/END #特殊模式,仅在awk命令的program运行之前(BEGIN)或运行之后(END)执行一次;BEGIN写在action前面,END写在action后面。
(5)Empty:空模式,匹配任意行;
action
常见的action有这么几类:
(1) Expressions #表达式
(2) Control statements #控制语句
(3) Compound statements #混合模式
(4) input statements #应该是赋值语句
(5) output statements #输出语句
对行进行的一系列操作都写在action中,在上面和下面的例子中有很多,不做特别介绍。
控制语句
(1)if-else
格式:if (condition) {then body} else {else body}
[root@www tmp]# awk ‘BEGIN{FS=":"}{if($3>=500){print $1,"common user"}else{print $1,"system user"}}‘ /etc/passwd root system user ....... nfsnobody common user oprofile system user baby common user
(2)while
格式:while (condition) {while body}
对/etc/passwd中的字段逆序输出:
[root@www tmp]# awk ‘BEGIN{FS=":"}{i=NF;while(i>0){printf("%10s",$i);i--};print ""}‘ /etc/passwd /bin/bash /root root 0 0 x root /sbin/nologin /bin bin 1 1 x bin
(3)do-while循环
格式:do {do-while body} while (condition)
与while循环类似,区别在于while会先判断条件在执行循环体,而do-while不管条件是否成立会先执行一次循环体再判断条件。
(4)for循环
格式:for (variable assignment; condition; iteration process) {for body}
[root@www tmp]# awk -F: ‘{for(i=NF;i>0;i--){printf("%-12s",$i)}print ""}‘ /etc/passwd
例子与while中的相似,printf可以对输出的字段格式化,printf在输出信息之后不会自动换行,所以在一行内容循环完成之后加上print "",完成换行。
(5)case语句
格式:switch (expression) {case VALUE or /RGEEXP/: statement1;... default: stementN}
在centOS上默认安装的awk好像不支持case语句,然后查看了一下文档(好像要在编译安装时添加--enable-switch):
(6)循环控制
break #跳出循环
continue #停止本次循环,直接进行下一个循环
这两个跟其他的编程语言用法一样。
(7)next #提前结束对本行的处理进而进入下一行的处理;
输出UID为基数的用户:
[root@www tmp]# awk -F: ‘{if($3%2==0) next;print $1,$7}‘ /etc/passwd bin /sbin/nologin adm /sbin/nologin sync /bin/sync halt /sbin/halt
简单介绍下printf的用法
格式:printf("format",item1,item2,...)
format用来指定后面的字段输出的格式,format格式的指示符都用%开头,后跟一个字符:
%c #显示字符的ASCII码
%d, %i #十进制整数
%e, %E #科学计数法显示数值
%f #显示浮点数
%g, %G #以科学计数法格式或浮点数格式显示数值
%s #显示字符串
%u #显示无符号整数
%% #显示%自身
修饰符:
num:显示宽度 #例:%10s,后面对应的字符长度为10(默认右对齐)
-:左对齐 #例:%-10s
+:显示数值的符号
.num: 取值精度 #例:%7.4f,总长度为7位,小数点后面精确到4位
[root@www tmp]# awk ‘BEGIN{FS=":"}{printf("%-10s%-10s\n",$1,$7)}‘ /etc/passwd root /bin/bash bin /sbin/nologin daemon /sbin/nologin ........
数组
这里使用的数组是关联数组(array[index-expression]),数组中的索引(index-expression)可以使用任意字符串,如果某数组元素事先不存在,那么在引用时,awk会自动创建此元素并将其初始化为空串。
数组的赋值,遍历,删除(删除元素使用delete array[index]):
[root@www ~]# awk ‘BEGIN{line[1]="a";line[2]="b";line[3]="c";for(i in line){print i,line[i]}}‘ 1 a 2 b 3 c [root@www tmp]# awk ‘BEGIN{line[1]="a";line[2]="b";line[3]="c";for(i in line){delete line[2];print i,line[i]}}‘ 1 a 2 3 c
对passwd中的用户逆序输出:
[root@www tmp]# awk -F: ‘{line[NR]=$1}END{for(i=NR;i>0;i--){print i,line[i]}}‘ /etc/passwd 29 baby 28 oprofile 27 tcpdump 26 sshd ............
内置函数
简单介绍几个常用的内置函数。
1)split(string,array[,fieldsep[,seps]])
将string表示的字符串以fieldsep为分隔符进行切片,并切片后的结果保存至array为名的数组中;数组下标从1开始
[root@www ~]# awk ‘{split($1,name,":");print name[1],name[7]}‘ /etc/passwd root /bin/bash bin /sbin/nologin daemon /sbin/nologin adm /sbin/nologin
2)length(string) #返回给定字串的长度
[root@www tmp]# awk -F: ‘{print length($1)}‘ /etc/passwd 4 3
3)substr(string,start[,length])
从string中截取子串,start为起始位置,length为截取的长度。
更详细的说明查看http://www.gnu.org/software/gawk/manual/gawk.html
.................^_^
原文地址:http://ljbaby.blog.51cto.com/10002758/1675684