Linux awk命令(一)基础

awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理,它能提供一个类编程环境来修改和组织文件中的数据。它比sed功能更为强大,可以看看sed的使用:
Linux sed命令(一)基础
Linux sed命令(二)进阶
awk分别代表其作者姓氏的第一个字母,它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,在所有的发行版中默认没有安装gawk,我们可以手动安装。

使用awk,你可以做以下事情:

  • 定义变量来保存数据
  • 使用算数和字符串操作符来处理数据
  • 使用结构化编程的概念的逻辑来处理数据
  • 通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告

一、awk命令格式

awk命令格式如下:

awk  [options]   program_script   file

option指定命令行选项,如:

-F fs           指定行中划分数据字段的字段分隔符
-f file         从指定的文件中读取awk程序
-v var=value    指定awk程序中的一个变量及其默认值
...

我们会在探索awk时逐渐的使用这些命令行选项。
awk强大之处在于program程序脚本,可以用脚本来读取文本行的数据,然后处理并显示数据,创建任何类型的报告。awk程序中脚本使用一对大括号{}来定义,并且由于awk命令行假定脚本是单个文本字符串,你还必须将脚本放在单引号中,即 '{ program_script}'

数据字段变量:

awk会将如下变量给配给它在文本行中发现的数据字段:

$0 代表整个文本行
$1 代表文本行中的第1个字段
$2 代表文本行中的第2个字段
...
$n 代表文本行中的第n个字段

在文本行中,每个字段都是通过字段分隔符划分的,默认的字段分隔符是空白字符(如空格、制表符)。当然,我们可以通过-F选项修改字段分隔符。请看示例,我们使用这一行命令awk -F: -f script1.awk /etc/passwd来输出用户名及其目录,注意首先用-F改变了字段分隔符,然后又用-f指定了脚本,脚本中只有一行代码 {print $1 "'s home is " $6},将脚本命名为.awk只是为了便于我们区分。运行它,可以得到类似下面的输出:

root's home is /root
daemon's home is /usr/sbin
bin's home is /bin
sys's home is /dev
...

BEGIN和END使用:

默认情况下,awk会从输入中读取一行文本然后针对这一行的数据执行程序脚本。有时可能需要在处理数据前或后运行脚本,比如创建标题和添加页脚说明等。这时我们就要使用BEGIN和END关键字。

# script1.awk
BEGIN {
print "This is the title line"
print "Change the FS"
FS=":"
}

{print $1 "'s home is " $6}

END{
print "This is the end line."
}

# 执行命令
awk  -f script1.awk /etc/passwd

如上代码所示,我们在脚本里使用了BEGIN和END,并且在BEGIN中指定了分隔符FS。在终端运行命令后,会发现输出的首末行会有我们在BEGIN和END中写的提示语。

二、awk中的变量

awk中使用支持两种不同的类型变量:内建变量和自定义变量。

2.1、內建变量

使用內建变量来引用程序数据里的一些特殊功能。

1、字段和记录分隔符变量
数据字段(field)是由字段分隔符(field separator)来划定的,前面我们提到过。gawk的输入可以从标准输入或指定的档案里读取,输入的读取单位被称为”记录”(records),gawk 在做处理时,是一个记录一个记录地处理。每个记录的默认值是一行(line),一个记录又被分为多个字段(fields)。

我们既然可以修改字段分隔符(field separator)来修改字段的读取方式,那么也可以修改记录分隔符(record separator)来分隔记录。

变量描述
FIELDWIDTHS由空格分隔的一列数字,定义每个数据字段的宽度
FS输入字段分隔符(默认是空格和tab)
RS输入记录分隔符(默认是换行)
OFS输出字段分隔符
ORS输出记录分隔符

~

FIELDWIDTHS允许你不依靠字段分隔符来读取记录,一旦设置了FIELDWIDTHS,就会忽略FS变量,并且不能再次改变,不适合用于变长的字段。

#data1
AAAAAHjgisg jkgkj
232 jlj
hoihgl
5555-2424

BBBBLhojlgs jk
435 jk
onnaga
5252-2525

CCCCQjlsjt jlkg
435 jlkjl
opjgsn
4521-5929

如上所示,我们如果要把每四行当做一个记录读取呢?很显然FS应该设置为换行符\n,那么RS应该怎么设置呢?我们可以用空白行来当做记录分隔符。可以写出以下awk代码:

BEGIN {
FS="\n";RS="";OFS="-"
}

{print $1,$4}

END{
print "This is the end line."
}

运行之后得到输出,我们使用了输出字段分隔符-来分隔输出,如下图:

awk

2、数据变量
除了FS和RS等一系列变量,还有一些內建变量来帮助你了解数据发上了什么变化。主要的变量如下表:

变量描述
ARGC当前命令行参数个数,ARGument COUNT
ARGV包含命令行参数的数组
ARGIND当前文件在ARGV中的位置
ENVIRON当前shell环境变量及其值组成的关联数组
FILENAME用作awk输入数据的数据文件的文件名
FNR当前数据文件中的数据行数
NF数据文件中字段总数
NR已处理的输入记录数

~
见如下使用NF和NR的示例,当我们不知道一条记录里面的字段时,可以用$NF来引用最后一个字段;没处理一条记录时NR的值就会加1,注意在脚本中引用awk变量时,变量名前不用加美元符号,这和shell中引用变量不同,如下面的NR。

#script1.awk
BEGIN {
FS=":";OFS="-"
}

{print $1,$NF,NR}

END{
}

#awk脚本
awk  -f script1.awk /etc/passwd

执行后,可得到以下期望的输出:

awk2

2.2、自定义变量:

1、在脚本中给变量赋值
和shell脚本中一致,有赋值语句即可。并且还支持数值运算,如下:

awk3

2、在命令行中给变量赋值
如下所示,我们在BEGIN和命令当中用到了变量n,但是还没有定义,可以在命令行中用n=的方式来为n指定数值。

BEGIN {
print "Print the ",n," field."
}

{print $n}

END{
}

awk4

需要注意的是在命令行中设置了变量值以后,BEGIN中并不可以直接用!这时我们要在变量定义的前面加上-v 来在BEGIN代码之前设定变量。

三、awk使用数组

awk中使用的是关联数组,它和数字数组不同的是索引可以是任意文本字符串。其实,关联数组和字典、散列表这些东西是一个概念的。

1、定义数组变量

var[key] = value

2、遍历数组变量
和多数语言一样,遍历数组采取for循换即可:

for(var in array)
{
    statements
}

awk5

输出如下所示,可以看出对数组的支持还是不错的,足够我们使用。

lupu@ubuntu:~$ awk  -f script1.awk 
key: Onlsgn  value: Lkongn
key: Ajgsl  value: Ihono
key: Qlgns  value: Pnwl
key: 1  value: 1
key: 2  value: 2
key: 3  value: 3
4
1

3、删除数组变量

删除数组索引就可以了:delete array[key]

四、使用模式匹配

awk中同样支持使用模式匹配来过滤数据记录,这和sed中的很相似。

1、正则表达式(re)
使用re时,必须使它出现在它要控制的程序脚本的左花括号前。使用起来很简单,如下图所示:

awk6

2、匹配操作符
使用匹配操作符来更精确的控制将要匹配的字段,$n ~ /expression/,即这里匹配了满足第n个字段是expression的情况。请看以下简单示例:

#匹配/etc/passwd文件中第一个字段一sys开头的记录,并输出第一个字段
lupu@ubuntu:~$ awk -F: '$1 ~ /^sys/{print $1}' /etc/passwd
sys
systemd-timesync
systemd-network
systemd-resolve
systemd-bus-proxy
syslog

我们也可以用!来排除正则表达式的匹配,$n ! ~ /expression/

3、数学表达式
当匹配数据字段中有数值时,用数学表达式来匹配非常方便。比如我们用命令ps -ef > ps.log将当前进程信息写入文件中,如果我们需要找出UID大于9000的进程那么可以这么来写命令:awk '$2 > 9000{print $0}' ps.log

awk7

可以使用任何比较常见的表达式。

  • x == y
  • x <= y
  • x >= y
  • x < y
  • x > y

也可以对文本数据使用表达式,但是必须注意的是,只有表达式完全一样才可以匹配。不能使用正则表达式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值