Linux awk命令

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

使用方法   : awk '{pattern + action}' {filenames}

尽管操作可能会很复杂,但语法总是这样,其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号({})不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。 pattern就是要表示的正则表达式,用斜杠括起来。

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

命令行格式:

$  awk [options] 'command' files

command 由两部分组成,分别是

  1、pattern,可以是正则表达式或者逻辑判断式

  2、{ awk 命令 }    花括号括起来的是代码段

脚本格式:

$ awk -f scirpt_file files

awk内置变量

变量含义
$0当前记录(整行的记录)
$1~$n当前记录的第几列
FILENAME输入的文件名称
FS输入文件的字段分隔符(Fields Separator)
RS输入文件的记录(每一行之间)的分隔符(Record Separator)
NF当前行的字段数目(Number of Fields)
NR当前记录所在的行号
OFS输出字段的分隔符
ORS输出记录的分隔符

awk函数

函数声明含义
length(str)返回str中字符的个数
int(num)返回num的整数部分
index(str1, str2)返回str2在str1中的索引,如果不存在就返回0
split(str, arr, separator)使用separator作为分隔符,将str切分为数组保存到arr中,返回数组的元素个数
printf(fmt, args)根据fmt格式化args,并输出结果
sprintf(fmt, args)根据fmp格式化args,并返回格式化后的字符串
substr(str, pos, len)返回str中从pos开始,长度为len个字符的子字符串
tolower(str)返回str转换为小写字母后的副本
toupper(str)返回str转换为大写字母后的副本

测试数据

-> # cat data.txt
小红    female     一年级   BeiJing      90     Yes
小花    female     一年级   ShangHai     55
小明    male       三年级   BeiJing      90
小可    female     一年级   ChongQing    70
小林    male       一年级   ChongQing    90     Yes
小飞    male       二年级   GuangDong    65
小波    male       一年级   HangZhou     90     No
小康    male       四年级   ShenZhen     65     No
小雷    male       一年级   FuJian       70
小冰    female     五年级   BeiJing      90

测试awk变量和函数

  打印每一行的行号、字段数、以及每一行的内容

-> # awk '{print "row:" NR "\t" "fields:" NF "\t" $0}' data.txt
row:1   fields:6        小红    female     一年级   BeiJing      90     Yes
row:2   fields:5        小花    female     一年级   ShangHai     55
row:3   fields:5        小明    male       三年级   BeiJing      90
row:4   fields:5        小可    female     一年级   ChongQing    70
row:5   fields:6        小林    male       一年级   ChongQing    90     Yes
row:6   fields:5        小飞    male       二年级   GuangDong    65
row:7   fields:6        小波    male       一年级   HangZhou     90     No
row:8   fields:6        小康    male       四年级   ShenZhen     65     No
row:9   fields:5        小雷    male       一年级   FuJian       70
row:10  fields:5        小冰    female     五年级   BeiJing      90

 打印所有的人名、城市

-> # awk '{print $1 "\t" $4}' data.txt
小红    BeiJing
小花    ShangHai
小明    BeiJing
小可    ChongQing
小林    ChongQing
小飞    GuangDong
小波    HangZhou
小康    ShenZhen
小雷    FuJian
小冰    BeiJing

使用printf来格式化打印用户信息

-> # awk -F ':' '{printf("Line:%s   Fields:%s   User:%s\n", NR, NF, $1)}' /etc/passwd
Line:1   Fields:7   User:root
Line:2   Fields:7   User:bin
Line:3   Fields:7   User:daemon
Line:4   Fields:7   User:adm
Line:5   Fields:7   User:lp
Line:6   Fields:7   User:sync
Line:7   Fields:7   User:shutdown

打印用户id大于100的行号和用户名,其他用户不打印,输出hello

-> # awk -F ':' '{
>    if ($3 > 100) {
>        printf("Line:%s   Fields:%s   User:%s   UID:%s\n", NR, NF, $1, $3)
>    } else {
>        print "hello"
>    }
> }' /etc/passwd

找出服务器访问日志中,出现Error的时间

-> # sed -n '/Error/ p' access_log | awk '{print $1}'
-> # awk '/Error/ {print $1}' access_log

逻辑判断式

注意,逻辑判断式是在{ awk命令 }前面的

~,!~     是否匹配正则表达式,后面跟一个正则表达式

-> # #查询主机中,用户名包含'g'的用户,打印出用户名和UID
-> # awk -F ':' '$1 ~ /g/ {print "User:"$1 "\t" "UID:"$3}' /etc/passwd
User:games      UID:12
User:libstoragemgmt     UID:998
User:syslog     UID:996
User:yingjie    UID:1005
 
-> # #查询主机中,用户名不包含'g'的用户,打印出用户名和UID
-> # awk -F ':' '$1 !~ /g/ {print "User:"$1 "\t" "UID:"$3}' /etc/passwd

==,!= , >=,<=,<,> ,||,&&   用于判断大小、是否相等、逻辑关系

-> # #打印分数高于70,或者低于或者等于60的记录
-> # awk '$5 > 70 || $5 < 60 {print $0}' data.txt
小红    female     一年级   BeiJing      90     Yes
小花    female     一年级   ShangHai     55
小明    male       三年级   BeiJing      90
小林    male       一年级   ChongQing    90     Yes
小波    male       一年级   HangZhou     90     No
小冰    female     五年级   BeiJing      90

扩展格式

$ awk [options]  'command' file

扩展格式是指,command扩展,格式如下:

  BEGIN { command1 } pattern { awk命令 } END { command2 }

  其中 BEGIN中的command1,会在读入第一行之前执行,并且只执行一次。接着循环执行中间的awk命令、

  然后END后面的command2,会在文件所有行都读完之后,并执行一次command2。

-> # awk 'BEGIN {print "start"} /female/ {print $0} END {print "end"}' data.txt
start
小红    female     一年级   BeiJing      90     Yes
小花    female     一年级   ShangHai     55
小可    female     一年级   ChongQing    70
小冰    female     五年级   BeiJing      90
end

BEGIN和END

  一般在BEGIN中可以做一下事情:

  1、定义分隔符

  2、定义表头  

 

  自定义分割符、输出时使用的分隔符

  FS (fields separator)

  OFS( output fields separator)

-> # awk 'BEGIN{FS=" ";OFS="-"}{print $2,$1}' data.txt
female-小红
female-小花
male-小明
female-小可
male-小林
male-小飞
male-小波
male-小康
male-小雷
female-小冰

定义表头

-> #  awk '
> BEGIN {print "Name" "\t"  "Gender" "\t" "Grade" "\t" "Addr" "\t" "Score" "\t" "VIP"}
> NF == 6 {print $0}
> END {print "----------end-----------"}' data.txt
Name    Gender  Grade   Addr    Score   VIP
小红    female  一年级   BeiJing    90     Yes
小林    male    一年级   ChongQing  90     Yes
小波    male    一年级   HangZhou   90     No
小康    male    四年级   ShenZhen   65     No
----------end-----------

统计当前文件夹下,文件总大小

[root@VM_0_8_centos test]# ls -l
total 8
-rw-r--r-- 1 root root  367 Sep 16 11:51 data.txt
-rw-r--r-- 1 root root 1803 Aug 17 00:14 test.cpp
[root@VM_0_8_centos test]# ls -l | awk 'BEGIN {size=0} {size+=$5} END {print "Size is " size}'
Size is 2170

统计文件中非空行的行数

[root@VM_0_8_centos test]# cat demo.txt
11111
 
22222
 
33333
44444
[root@VM_0_8_centos test]# awk 'BEGIN {count=0} $0 !~ /^$/ {count += 1} END {print "Not empty line count " count}' demo.txt
Not empty line count 4

统计女生的数量

-> # awk '
> BEGIN {count = 0}
> {
>    if ($2 == "female") {
>       name[count++] = $1
>   }
> }
> END {
>   print "tot " count
>   for (i = 0; i < count; i++) {
>     print name[i]
>   }
> }' data.txt
tot 4
小红
小花
小可
小冰

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值