linux awk详解

1.字段的理解

awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。

在学习之前先熟悉一个字段:/etc/passwd中的字段
这里写图片描述
/etc/passwd中,每行包含7个字段(从1开始数共7个),他们分别代表:用户名:密码:用户ID:组ID:描述:主目录:默认shell
第二个字段就是密码,一般加密后放在/etc/shadow里;

具体的详细信息如下:
1)“用户名”是代表用户账号的字符串。通常长度不超过8个字符,并且由大小写字母和/或数字组成。登录名中不能有冒号(,因为冒号在这里是分隔符。为了兼容起见,登录名中最好不要包含点字符(.),并且不使用连字符(-)和加号(+)打头。

2)“口令”一些系统中,存放着加密后的用户口令字。。虽然这个字段存放的只是用户口令的加密串,不是
明文,但是由于/etc/passwd文件对所有用户都可读,所以这仍是一个安全隐患。因此,现在许多 Linux
系统(如SVR4)都使用了shadow技术,把真正的加密后的用户口令字存放到/etc/shadow文件中,而在/etc/passwd文件的口令字
段中只存放一个特殊的字符,例如“x”或者“*”。

3)“用户标识号”是一个整数,系统内部用它来标识用户。一般情况下它与用户名是一一对应的。如果几个用户名对应的用户标识号是一样的,系统内部将把它们视为同一个用户,但是它们可以有不同的口令、不同的主目录以及不同的登录Shell等。

通常用户标识号的取值范围是0~65 535。0是超级用户root的标识号,1~99由系统保留,作为管理账号,普通用户的标识号从100开始。在Linux系统中,这个界限是500。

4)“组标识号”字段记录的是用户所属的用户组。它对应着/etc/group文件中的一条记录。

5)“注释性描述”字段记录着用户的一些个人情况,例如用户的真实姓名、电话、地址等,这个字段并没有什么实际的用途。在不同的Linux
系统中,这个字段的格式并没有统一。在许多Linux系统中,这个字段存放的是一段任意的注释性描述文字,用做finger命令的输出。

6)“主目录”,也就是用户的起始工作目录,它是用户在登录到系统之后所处的目录。在大多数系统中,各用户的主目录都被组织在同一个特定的目录下,而
用户主目录的名称就是该用户的登录名。各用户对自己的主目录有读、写、执行(搜索)权限,其他用户对此目录的访问权限则根据具体情况设置。

7)用户登录后,要启动一个进程,负责将用户的操作传给内核,这个进程是用户登录到系统后运行的命令解释器或某个特定的程序,即Shell。
Shell 是用户与Linux系统之间的接口。Linux的Shell有许多种,每种都有不同的特点。常用的有sh(Bourne Shell),
csh(C Shell), ksh(Korn Shell), tcsh(TENEX/TOPS-20 type C Shell),
bash(Bourne Again
Shell)等。系统管理员可以根据系统情况和用户习惯为用户指定某个Shell。如果不指定Shell,那么系统使用sh为默认的登录Shell,即这个字段的值为/bin/sh。
用户的登录Shell也可以指定为某个特定的程序(此程序不是一个命令解释器)。利用这一特点,我们可以限制用户只能运行指定的应用程序,在该应用程序运行结束后,用户就自动退出了系统。有些Linux 系统要求只有那些在系统中登记了的程序才能出现在这个字段中。
cat /etc/group
组名:加密密码:组ID:所有属于该组的用户。
这里写图片描述

在对/etc/passwd 和/etc/passwd字段中的内容了解了之后,进入主题:

2.入门实例

awk ‘{pattern + action}’ {filenames}
其中 pattern 表示 AWK 在数据中查找的内容,一个Pattern是一个正则表达式经编译后的表现模式。而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。

注:awk语言的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后,才能进行其他文本操作。完整的awk脚本通常用来格式化文本文件中的信息。通常,awk是以文件的一行为处理单位的。awk每接收文件的一行,然后执行相应的命令,来处理文本。

#awk -F: ‘/root/’ /etc/passwd
这里写图片描述
这种是pattern的使用示例,匹配了pattern(这里是root)的行才会执行action(没有指定action,默认输出每行的内容)。

搜索支持正则,例如找root开头的:
awk -F: ‘/^root/’ /etc/passwd
这里写图片描述

搜索/etc/passwd有root关键字的所有行,并显示对应的shell
这里写图片描述

如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以tab键分割:
这里写图片描述

另外的:
假设last -n 5的输出如下:
这里写图片描述

如果只是显示最近登录的5个帐号
这里写图片描述

如果只是显示/etc/passwd的账户和账户对应的shell,而账户与shell之间以逗号分割,而且在所有行添加列名name,shell,在最后一行添加”blue,/bin/nosh”。
这里写图片描述
awk工作流程是这样的:先执行BEGING,然后读取文件,读入有/n换行符分割的一条记录,然后将记录按指定的域分隔符划分域,填充域, 0, 1表示第一个域,$n表示第n个域,随后开始执行模式所对应的动作action。接着开始读入第二条记录······直到所有的记录都读完,最后执行END操作。

3.awk内置变量

ARGC               命令行参数个数
ARGV               命令行参数排列
ENVIRON            支持队列中系统环境变量的使用
FILENAME           awk浏览的文件名
FNR                浏览文件的记录数
FS                 设置输入域分隔符,等价于命令行 -F选项
NF                 浏览记录的域的个数
NR                 已读的记录数
OFS                输出域分隔符
ORS                输出记录分隔符
RS                 控制记录分隔符

统计/etc/passwd:文件名,每行的行号,每行的列数,对应的完整行内容:
这里写图片描述

使用printf替代print,可以让代码更加简洁,易读
awk -F ‘:’ ‘{printf(“filename:%10s,linenumber:%s,columns:%s,linecontent:%s\n”,FILENAME,NR,NF,$0)}’ /etc/passwd
这里写图片描述

下面做个awk 内置变量 NF NR的小实验:
1)NF:
grep “Failed” /var/log/secure:
这里写图片描述

grep “Failed” /var/log/secure | awk ‘{print $(NF-3)}’:
这里写图片描述
NF-3的意思是倒数第三个字段,ssh2是第-0个字段,663951是第-1个字段….192.168.33.20是第-3个字段。

同理# grep “Failed” /var/log/secure | awk ‘{print $(NF-9)}’结果为:
这里写图片描述

它和# grep “Failed” /var/log/secure | awk ‘{print $(5)}’命令结果是一样的:
这里写图片描述

上面的例子是 NF NF,如果是NF就不同了,NF就代表被(默认)空格分开的域的个数:
这里写图片描述

2)NR:
NR代表执行的行数:也就是假如bbb.log的文本有如下内容:
111b

222b
那么:grep “1” bbb.log | awk ‘{print NR}’
就会返回:1
那么:grep “2” bbb.log | awk ‘{print NR}’
就会返回:2
那么:grep “b” bbb.log | awk ‘{print NR}’
就会返回:
1
2

假设bbb.log的文本有如下内容:
111b

222b
333c
444d
555b
grep “b” bbb.log | awk ‘{print NR}’
返回:
1
2
3
这里写图片描述

为什么是1 2 3 而不是1 2 5 不是行数么?

因为grep “b” bbb.log的结果是:
111b
222b
555b
然后这个结果管道给awk的,所以1 2 3。

4.awk编程

变量和赋值
除了awk的内置变量,awk还可以自定义变量。
下面统计/etc/passwd的账户人数


awk ‘{count++;print $0;} END{print “user count is “, count}’ /etc/passwd

这里写图片描述
count是自定义变量。之前的action{}里都是只有一个print,其实print只是一个语句,而action{}可以有多个语句,以;号隔开。

这里没有初始化count,虽然默认是0,但是妥当的做法还是初始化为0:
awk ‘BEGIN {count=0;print “[start]user count is “, count} {count=count+1;print $0;} END{print “[end]user count is “, count}’ /etc/passwd
这里写图片描述

统计某个文件夹下的文件占用的字节数:
ls -l |awk ‘BEGIN {size=0;} {size=size+$5;} END{print “[end]size is “, size}’
这里写图片描述

如果以M为单位显示:
ls -l |awk ‘BEGIN {size=0;} {size=size+$5;} END{print “[end]size is “, size/1024/1024,”M”}’
这里写图片描述

条件语句
awk中的条件语句是从C语言中借鉴来的,见如下声明方式:

if (expression) {
    statement;
    statement;
    ... ...
}

if (expression) {
    statement;
} else {
    statement2;
}

if (expression) {
    statement1;
} else if (expression1) {
    statement2;
} else {
    statement3;

例如,统计某个文件夹下的文件占用的字节数,过滤4096大小的文件(一般都是文件夹):
ls -l |awk ‘BEGIN {size=0;print “[start]size is “, size} {if($5!=4096){size=size+$5;}} END{print “[end]size is “, size/1024/1024,”M”}’
这里写图片描述

循环语句
awk中的循环语句同样借鉴于C语言,支持while、do/while、for、break、continue,这些关键字的语义和C语言中的语义完全相同。

数组
因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的。数组和变量一样,都是在使用时自动创建的,awk也同样会自动判断其存储的是数字还是字符串。一般而言,awk中的数组用来从记录中收集信息,可以用于计算总和、统计单词以及跟踪模板被匹配的次数等等。

下面使用for循环遍历数组,显示/etc/passwd的账户:
awk -F ‘:’ ‘BEGIN {count=0;} {name[count] = $1;count++;}; END{for (i = 0; i < NR; i++) print i, name[i]}’ /etc/passwd
这里写图片描述

awk编程的内容极多,这里只罗列简单常用的用法,更多请参考 http://www.gnu.org/software/gawk/manual/gawk.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值