• 进入"运维那点事"后,希望您第一件事就是阅读“关于”栏目,仔细阅读“关于Ctrl+c问题”,不希望误会!

Linux命令:awk

系统管理 彭东稳 9年前 (2015-09-01) 26436次浏览 已收录 0个评论

一、Awk介绍

Awk、sed与grep,俗称Linux下的三剑客,它们之间有很多相似点,但是同样也各有各的特色,相似的地方是它们都可以匹配文本,其中sed和awk还可以用于文本编辑,而grep则不具备这个功用。sed是一种非交互式且面向字符流的编辑器(a “non-interactive” stream-oriented editor),而awk则是一门模式匹配的编程语言,因为它的主要功能是用于匹配文本并处理,同时它有一些编程语言才有的语法,例如函数、分支循环语句、变量等等,当然比起我们常见的编程语言,Awk相对比较简单。

Awk其名称得自于它的创始人Alfred Aho 、Peter Weinberger和Brian Kernighan姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。AWK支持基本语言的变量,条件判断,循环,数组等,但是表现形式只有一行命令。

Awk有3个不同版本,分别为早期的awk、改版过的nawk和GNU的gawk,在Linux中awk实际上是gawk的一个符号链接。而gawk是也叫GNU awk是nawk的开源实现版本。

Awk就像个数据库,支持对记录和字段的处理。但是与数据库不同的是,它处理的是文本。默认的情况下,awk会将文本中的一行视为一个记录,而将一行中一个或多个非空白字符组成的单词视为字段,换句话说就是用空格来分隔字段。当然,这些都是默认情况。

使用Awk,我们可以做以下事情:

  • 将文本文件视为由字段和记录组成的文本数据库;
  • 在操作文本数据库的过程中能够使用变量;
  • 能够使用数学运算和字符串操作
  • 能够使用常见的编程结构,例如条件分支与循环;
  • 能够格式化输出;
  • 能够自定义函数;
  • 能够在awk脚本中执行UNIX命令;
  • 能够处理UNIX命令的输出结果;

Awk能够做得事情非常多,但千里之行,始于足下,我们首先从最基本的命令行语法开始,一步一步得走入awk的编程世界。

二、Awk语法介绍

命令语法:

Awk程序的核心思想是模式(pattern)/行为(action)对儿这个概念,也叫模式驱动编程。模式一般是关系式或正则表达式,用于与输入的每条记录进行匹配;Awk的输入被解析成多个记录(Record),默认情况下,记录的分隔符是\n,因此可以认为一行就是一个记录,记录的分隔符可以通过内置变量“RS”更改。当记录匹配某个pattern时,才会执行后续的action命令。模式或行为可以省略其中一个。如果省略模式,则行为将被应用到每条输入记录;如果省略行为,则默认操作是在标准输出上打印匹配到的记录。

而每个记录由进一步地被分隔成多个字段(Field),默认情况下字段的分隔符是空白符,例如空格、制表符等等,也可以通过“-F”选项或者内置变量“FS”更改。在awk中,可以通过$1,$2…来访问对应位置的字段,同时$0存放整个记录,这一点有点类似shell下的命令行位置参数。关于这些内容,我们会在下面详细介绍,这里你只要知道有这些东西就好。

Awk还提供了两种特殊的模式BEGIN和ENG。与BEGIN配对的行为只会被执行一次,且永远是最先执行的,而END则与BEGIN相反,永远是最后执行的且只执行一次,BEGIN/END都可以用来定义输出变量或输出信息,下图是awk的工作流程。

Linux命令:awk

BEGIN和END模式可以放在awk程序的任何位置。但是由于人的惯性思维,通常会将BEGIN模式放在程序的最开头,而将END模式放在程序的结尾处。一个awk程序可以有多个BEGIN和END模式,这个时候就按照他们出现的顺序依次执行。提供这种特性时允许使用“-f”命令选项引入程序库,提供库的初始化和清除操作。

为了便于理解,这里举几个简单的例子。通过-F参数设置冒号:为分隔符,并打印各个字段:

字段含义:

[options]

/pattern/

  • Regexp

正则表达式,格式为/regular exspression/

例如:

  • 表达式操作符(expression)
算术操作符 负值(-x)、转换为数值(+x)、次方(**)、乘(*)、除(/)、加(+)、减(-) 、取余(%)。
赋值操作符 等于(=)、加等(+=)、减等(-=)、乘等(*=)、除等(/=)、**/ 、++、–。
比较操作符 小于(<)、大于(>)、小于等于(<=)、大于等于(>=)、等于(==)、不等于(!=)、字符串匹配模式成功为真(~)、字符串匹配模式成功为假(!~)。
逻辑操作符 逻辑与(&&)、逻辑或(||)。

例如:

  • ranges

指定的匹配地址范围,如/part1/,/part2/

例如:

  • BEGIN/END

特殊模式,仅在awk命令执行前运行一次或结束前运行一次。

{action}

  • Output statements

print的使用格式:{Print item1,item2…}

1、各项目之间使用逗号隔开而输出时则以空白字符隔开,否则则当成一个字段处理。

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

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

例如:

printf的使用格式:{printf format,item1,itme2}

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

2、Printf语句不会自动打印换行符,需要加\n换行。

3、format用于指定后面的每个item的输出格式,如:

格式 含义
%c 显示字符的ASCII码
%d,%i 十进制整数
%e,%E 科学计数法显示数值
%f 显示浮点数
%g,%G 以科学计数法的格式或浮点数的格式显示数值
%s 显示字符串
%u 无符号整数
%% 显示%自身

例如:

修饰符:

例如:

  • control statements(跟shell语法不同)

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

while语法:while (condition) {statement1; statement2;…}

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

for语法:  for ( variable assignment ; condition; iteration process) {statment1,statment2,….}

for (i in array) {statement1,statement2,…}

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

PS:break和continue常用于循环和case语句中。

三、Awk内置变量

Awk在内部维护了许多内置变量,或者称为系统变量,例如之前提到的FS、RS等等。常见的内置变量如下表所示:

变量名 描述
ARGC 命令行参数的各个,即ARGV数组的长度
ARGV 存放命令行参数
CONVFMT 定义awk内部数值转换成字符串的格式,默认值为”%.6g”
OFMT 定义输出时数值转换成字符串的格式,默认值为”%.6g”
ENVIRON 存放系统环境变量的关联数组
FILENAME 当前被处理的文件名
NR 记录的总个数
FNR 当前文件中的记录的总个数
FS 字段分隔符,默认为空白
NF 每个记录中字段的个数
RS 记录的分隔符,默认为回车
OFS 输出时字段的分隔符,默认为空白
ORS 输出时记录的分隔符,默认为回车
RLENGTH 被match函数匹配的子串长度
RSTART 被match函数匹配的子串位于目标字符串的起始下标

简单可分为如下几类:

  • 记录变量

FS(field separator):输入使用的字段分隔符,默认是空格,可以自定义设置,如下:

OFS(output field separator):输出使用的字段分隔符

RS(record separator):输入使用的换行符(awk每次读取一行数据就是根据设定的默认换行符来辨别的)

ORS(output record separator):输出使用的换行符

  • 数据变量

NR:记录所处理的行,如果有多个文件,这个数目会把处理的多个文件中行统一计数(注意,在awk中打印变量不需要加$符,如果加$符那就是打印字段了)

FNR:记录所处理的行,如果有多个文件,这个数目会把处理的多个文件各自计数

NF:记录当前所处理文件行的字段数,(利用这个可以用来显示每行的最后一个字段)

ARGV:数组,保存命令行本身这个字符串,如ARVG[0]显示awk命令,而ARGV[1]显示跟的文件名

  • 用户自定义变量

gawk允许用户自定义自己的变量以便在程序代码中使用,变量名命名规则与大多数编程语言相同,只能使用字母、数字和下划线,且不能以数字开头,gawk变量名称区分字符大小写。

命令行中使用赋值变量,如:

脚本中赋值变量,如:

四、Awk数组使用

在awk中,数组跟shell中一样。但不同的是shell中数组下标一般都是从0开始而在awk中是从1开始。并且awk中的下标index可以使用任意字符串表示。如:

需要注意的是如果某数组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此要判断某数据组中是否存在某元素需要使用index in array的方式要遍历数组中的每一个元素需要使用如下的特殊结构For循环:

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

从关系数组中删除数组索引需要使用delete命令使用格式为Delete array[index]。

五、Awk内置函数

awk中包含大多数常见的字符串操作函数。

sub(ere, repl[, in])

描述:简单地说,就是将in中匹配ere的部分替换成repl,返回值是替换的次数。如果in参数省略,默认使用$0。替换的动作会直接修改变量的值。

gsub(ere, repl[, in])

描述:同sub()函数功能类似,只不过是gsub()是全局替换,即替换所有匹配的内容。

index(s, t)

描述:返回字符串t在s中出现的位置,注意这里位置是从1开始计算的,如果没有找到则返回0。

split(s, a[, fs])

描述:将字符串按照分隔符fs,分隔成多个部分,并存到数组a中。注意,存放的位置是从第1个数组元素开始的。如果fs为空,则默认使用FS分隔。函数返回值分隔的个数。

length[([s])]

描述:返回字符串的长度,如果参数s没有指定,则默认使用$0作为参数。

match(s, ere)

描述: 返回字符串s匹配ere的起始位置,如果不匹配则返回0。该函数会定义RSTART和RLENGTH两个内置变量。RSTART与返回值相同,RLENGTH记录匹配子串的长度,如果不匹配则为-1。

system([command])

描述:执行系统command并将结果返回至awk命令。

sprintf(fmt, expr, expr, …)

描述:类似printf,只不过不会将格式化后的内容输出到标准输出,而是当作返回值返回。

tolower(s)

描述:将字符串转换成小写字符。

toupper(s)

描述:将字符串转换成大写字符。

如果需要自定义函数使用function关键字即可,格式如下:

函数还可以使用return语句返回值格式为”return value”。

Awk支持管道或重定向

特殊设备文件描述符

The GNU Awk User’s Guide


如果您觉得本站对你有帮助,那么可以支付宝扫码捐助以帮助本站更好地发展,在此谢过。
喜欢 (0)
[资助本站您就扫码 谢谢]
分享 (0)

您必须 登录 才能发表评论!