linux之awk命令详解

AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。


AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。
它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言,
它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
最简单地说, AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,

尽管操作可能会很复杂,但命令的语法始终是:
awk '{pattern + action}' 或者 awk 'pattern {action}'

其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。

awk提供了一个完整的编程模型。

awk程序由一个主输入循环维持。并且反复执行。直到终止条件被触发。

但是这些处理都是由awk自己完成的。我们只需要编写循环中的处理。

会循环的处理pattern匹配的每一条数据,直到处理完毕。

awk中还定义了两个特殊的字段。BEGIN和END。BEGIN用于在主输入循环之前执行。即在未读取输入文件之前执行。END则相反,

用于在主输入循环之后执行。即在读取输入文件执行完毕后执行。

awk的调用方法也分为三种:

①awk [-F 域分隔符] 'awk程序段' 输入文件

②awk -f awk脚本文件 输入文件

③./awk脚本文件 输入文件(awk脚本需要以'#!'开头加上awk的路径,并且设置为可执行)

可以看到,第一种方式中,可以通过-F来指定域分隔符。那这是什么意思呢?

在awk中认为输入文件是结构化的,awk将每个输入文件行定义为记录。行中的每个字符串定义为域,域之间用空格,tab键或其他字符进行分割,分割的符号叫做分隔符。多个连续的空格或tab键被当作一个分隔符来处理。

在awk中定义了一个域操作符$来指定执行动作的域。域操作符后面跟数字或变量来标识域的位置。域的编号从1开始,0表示所有的域。

比如:zhangsan   男   24    江西  138xxxxxxxx

上面这条记录中,$0就代表了整条记录,$1就代表[zhangsan],$2就代表[男]。

尽管-F可以改变分隔符,但是在awk中还提供了一种更方便的方式来改变分隔符。就是awk环境变量FS。

我们可以通过在BEGIN字段中设置FS的值来改变分隔符。

下面就来简单体验下awk的简单使用:

[fuwh@localhost 12:42 ~/stu]$ cat tx
fuwh men:jiangxi
zhangsan girl:shanghai
[fuwh@localhost 12:45 ~/stu]$ awk '{print $2}' tx
men:jiangxi
girl:shanghai
[fuwh@localhost 12:46 ~/stu]$ awk -F":" '{print $2}' tx
jiangxi
shanghai
[fuwh@localhost 12:47 ~/stu]$ awk 'BEGIN {FS=":"} {print $1}' tx
fuwh men
zhangsan girl
[fuwh@localhost 12:48 ~/stu]$

awk既然也是一种编程语言,那里面肯定也是有很多普通语言所具有的运算符,循环,判断之类的。

在awk中awk程序段都是由模式和动作组成的。模式是一组用于测试输入行是否需要执行动作的规则,动作包含语句,函数和表达式的执行过程,在模式匹配中,经常需要用到正则表达式。awk支持'?'和'+'这两个元字符。

关系和布尔运算符

关系运算符主要用于awk模式匹配

<:小于

>:大于

<=:小于或等于

>=:大于或等于

==:等于

!=:不等于

~:匹配正则表达式

!~:不匹配正则表达式

布尔运算:

||:逻辑或

&&:逻辑与

!:逻辑非

例子

[fuwh@localhost 13:31 ~/stu]$ cat tx
fuwh:men:jiangxi
zhangsan:girl:shanghai
lisi:girl:beijing
wangwu:feman:shenzhen
[fuwh@localhost 13:31 ~/stu]$ awk 'BEGIN{FS=":"} {if($2=="men"||$2~/girl/) print $3}' tx
jiangxi
shanghai
beijing
[fuwh@localhost 13:34 ~/stu]$

表达式

在awk中也可以定义变量,一个表达式可以包含赋值,运算符等等。

+:加

-:减

*:乘

/:除

%:模

^或**:乘方

++x:自增,在返回x之前

x++:自增,在返回x之后

例子:

[fuwh@localhost 14:06 ~/stu]$ cat tx
fuwh:men:jiangxi
zhangsan:girl:shanghai
lisi:girl:beijing
wangwu:feman:shenzhen
[fuwh@localhost 14:10 ~/stu]$ awk 'BEGIN{FS=":"} {if($2=="girl") x++} END{print "女生个数:" x}' tx
女生个数:2
[fuwh@localhost 14:10 ~/stu]$

系统变量

在awk中,还内建了许多变量,用来设置环境信息 。叫做系统变量。

系统变量分为两种:一种是用于改变awk的默认值,如域分隔符FS,第二种用于定义系统值。在处理文本的时候可以读取这些系统值,如记录中的域数量,当前记录数,当前文件名之类的。

下面是一些常见的环境变量及其意义:

$n:当前记录的第n个域,域间由FS分割
$0:记录所有的域

ARGC:命令行参数的数量

ARGIND:命令行中当前文件的位置(以0开始标号)

ARGV:命令行参数的数组

CONVFMT:数字转换格式

ENVIRON:环境变量关联数组

ERRNO:最后一个系统错误的描述

FIELDWIDTHS:字段宽度列表,以空格键分割

FILENAME:当前文件名

FNR:浏览文件的记录数

FS:字段分隔符,默认是空格键

IGNORECASE:布尔变量,如果威震,则进行忽略大小写的匹配

NF:当前记录中的域数量

NR:当前记录数

OFMT:数字的输出格式

OFS:输出域分隔符,默认是空格键

ORS:输出记录分隔符,默认是换行符

RLENGTH:由match函数所匹配的字符串长度

RS:记录分隔符默认是空格键

RSTART:由match函数所匹配的字符串的第一个位置

SUBSEP:数组下标分隔符,默认是34

例子:

[fuwh@localhost 14:31 ~/stu]$ cat tx
fuwh:men:jiangxi
zhangsan:girl:shanghai
lisi:girl:beijing
wangwu:feman:shenzhen
[fuwh@localhost 14:31 ~/stu]$ awk 'BEGIN{FS=":"} {print "第"NR"条记录"} END{print FILENAME "共"FNR"条记录,每条有"NR"个域"}' tx
第1条记录
第2条记录
第3条记录
第4条记录
tx共4条记录,每条有4个域
[fuwh@localhost 14:32 ~/stu]$

格式化输出

前面我们都是用print进行输出,但是,在awk中,还提供了printf这个输出来进行格式化的输出工作。

基本语法:

printf (格式控制符,参数)

printf的语句分为两部分,第一部分是格式控制符,都以%开始,用以描述格式规范,第二部分是参数列表,比如变量名列表。与格式控制符相对应。

格式控制符又可以分为修饰符和格式符两种。

修饰符:

-:左对齐

width:域的步长

-prec:小数点右边的位数

格式符:

%c:ASCII字符

%d:整型数

%e:浮点数,科学计数法

%f:浮点数

%o:八进制数

%s:字符串

%x:十六进制数

例子:

[fuwh@localhost 14:35 ~/stu]$ cat tx
fuwh:men:jiangxi
zhangsan:girl:shanghai
lisi:girl:beijing
wangwu:feman:shenzhen
[fuwh@localhost 14:46 ~/stu]$ awk 'BEGIN{FS=":"}{printf("%s	%s人
",$1,$3) }' tx
fuwh    jiangxi人
zhangsan        shanghai人
lisi    beijing人
wangwu  shenzhen人
[fuwh@localhost 14:47 ~/stu]$

内置字符串函数

在awk中提供了强大的内置字符串函数,用于实现文本的字符串替换、查找以及分割等功能。

gsub(r,s):在输入文件中用s替换r

gsub(r,s,t):在t中用s替换r

index(s,t):返回s中字符串第一个t的位置

length(s):返回s的长度

match(s,t):测试s是否包含匹配t的字符串

split(s,t):在t上将r分成序列s

sub(r,s,t):将t中第一次出现的r替换成s

substr(r,s):返回字符串r中从s开始的后缀部分

例子:

[fuwh@localhost 14:59 ~/stu]$ cat tx
fuwh:men:jiangxi
zhangsan:girl:shanghai
lisi:girl:beijing
wangwu:feman:shenzhen
[fuwh@localhost 15:03 ~/stu]$ awk 'BEGIN{FS=":"}{if($1=="fuwh") print(length($3))}' tx
7
[fuwh@localhost 15:04 ~/stu]$

向awk脚本传递参数

在awk中使用的变量,可以在命令行中进行赋值。实现向awk脚本传递参数。变量复制放在脚本之后、输入文件之前,格式为:

awk 脚本 parameter=value 输入文件

 例子:

[fuwh@localhost 15:26 ~/stu]$ ll tx*
-rw-rw-r--. 1 fuwh fuwh 80 8月  14 13:31 tx
-rwxrw-r--. 1 fuwh fuwh 41 8月  14 15:26 tx.awk
[fuwh@localhost 15:26 ~/stu]$ cat tx tx.awk
fuwh:men:jiangxi
zhangsan:girl:shanghai
lisi:girl:beijing
wangwu:feman:shenzhen
#!/bin/awk -f
{printf("%s	%s
",$1,$3)}
[fuwh@localhost 15:26 ~/stu]$ ./tx.awk FS=":" tx
fuwh    jiangxi
zhangsan        shanghai
lisi    beijing
wangwu  shenzhen
[fuwh@localhost 15:26 ~/stu]$

条件语句和循环语句

 awk中支持下面几种条件语句和循环语句。

if(条件表达式)

  动作1

[else

  动作2]

 while(条件表达式)

  动作

do

  动作

while(条件表达式)

for(计数器初始值;测试计数器条件;计数器变化)

  动作

数组

数组的索引可以是数字,也可以是字符串,索引并不表示存储的顺序信息。在awk中,会自动维护一对索引和值的信息。

awk中访问数组的所有元素:

for(变量 in 数组名)

  xxxxx

还可以使用in来判断是否在数组中存在

  索引名 in 数组名

如果存在,则返回1,不存在则返回0

原文地址:https://www.cnblogs.com/zerotomax/p/7356470.html