码迷,mamicode.com
首页 > 其他好文 > 详细

awk用法详解

时间:2015-07-17 23:07:36      阅读:266      评论:0      收藏:0      [点我收藏+]

标签:文本编辑器   awk   awk详解   

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

.................^_^


awk用法详解

标签:文本编辑器   awk   awk详解   

原文地址:http://ljbaby.blog.51cto.com/10002758/1675684

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!