M25_第九周:awk

[TOC]

AWK介绍

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

awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。

awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。

AWK工作原理

第一步:执行BEGIN{action;... }语句块中的语句
第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;... }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。
第三步:当读至输入流末尾时,执行END{action;...}语句块BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中END
语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END
语句块中完成,它也是一个可选语句块pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供
pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

使用方法

基本格式:awk [options] 'program' file...

program:pattern {action statements;..}

pattern和action:

BEGIN,END
action statements对数据进行处理,放在{}内指明
print,printf

分割符、域和记录

awk执行时,由分隔符分隔的字段(域)标记$1,$2..$n称为域标识。$0为所有域,注意:和shell中变量$符含义不同
文件的每一行称为记录
省略action,则默认执行print $0 的操作

格式和变量

print格式:

print item1, item2, ...
要点
(1) 逗号分隔符
(2) 输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式
(3) 如省略item,相当于print $0

awk内置变量:

FS或-F:输入字段分隔符,默认为空白字符

FS实例:
[ root@CentOS ~]#awk    '{print $1}' score.txt    
mage
wang
zhang
li
---------------------------------------------------------------
[ root@CentOS ~]#awk  -v FS=':' '{print $1,$3}' score2.txt 
mage male
wang male
zhang female
li female
[ root@CentOS ~]#cat score2.txt 
mage:100:male
wang:90:male
zhang:80:female
li:100:female
//-v FS=":"以":"分割符,取出文本中的$1(第一列)、$3(第三列)。注意:分割符(":")必须是文本中内容有的,如果文中没有 ":"是没有结果的,如下:
[ root@CentOS ~]#awk -v FS=":" '{print $1,$3}' score.txt          
mage 100 male 
wang 90 male 
zhang 80 female 
li 100 female
//他就会打印全部
-F:实例
[ root@CentOS ~]#awk  -F: '{print $1,$3}' score2.txt 
mage male
wang male
zhang female
li female
//跟FS效果一样,只不过选项格式不一样

OFS:输出字段分隔符,默认为空白字符

[ root@CentOS ~]#awk  -F: -v OFS='-' '{print $1,$3}'  score2.txt 
mage-male
wang-male
zhang-female
li-female
//先以 ":"分割,OFS='-',指定输出的分隔符

RS:输入记录分隔符,指定输入时的换行符,原换行符仍有效

[ root@CentOS ~]#awk -v RS=':' '{print $0}' score2.txt 
mage
100
male
wang
90
male
zhang
80
female
li
100
female
//-v RS=':' :RS(行处理),在内容中碰到':'就换行,输入时的换行符

ORS:输出时的换行符

[ root@CentOS ~]#awk -F: -v ORS='--' '{print $0}' score2.txt   
mage:100:male--wang:90:male--zhang:80:female--li:100:female--
//先以 ":"分割,输出时以 '--'的分割符

NF:字段数量

[ root@CentOS ~]#awk  -F: '{print NF}' score2.txt 
3
3
3
3
1
//查看文件有几个字段,如果写成$NF意义就不一样了。awk 中声明的变量在print 里面无需写'$'
[ root@CentOS ~]#awk  -F: '{print $NF}' score2.txt 
male
male
female
female
  100 female
 //打印出score2.txt文件的每行词尾,因为NF是打印每行的字段数量,如果写成$NF那就是NF的结果,如果NF是2,那么输入$NF显示的是2字段的字符串

NR:行号

[ root@CentOS ~]#awk  '{print NR}' score2.txt 
1
2
3
4
5
[ root@CentOS ~]#cat score2.txt 
mage:100:male
wang:90:male
zhang:80:female
li:100:female
li :  100 female
//显示行号

FNR:各文件分别计数,行号

[ root@CentOS ~]#awk  '{print $0,FNR}'  score.txt 
mage 100 male 1
wang 90 male 2
zhang 80 female 3
li 100 female 4
//后面的数字显示的是行数编号

FILENAME:当前文件名

[ root@CentOS ~]#awk  '{print FILENAME}' score.txt 
score.txt
score.txt
score.txt
score.txt
//因为score.txt里面有5行所有打印了5次,当然我们也可以使用一种模式让他只打印一次
[ root@CentOS ~]#awk  'END{print FILENAME}' score.txt      
score.txt
// END后面会讲到

ARGC:命令行参数的个数

[ root@CentOS ~]#awk  '{print ARGC}' score2.txt   
2
2
2
2
2
//当前有2个参数,一个是awk,一个是score2.txt,打印5次是因为score2文件中有5行

ARGV:数组,保存的是命令行所给定的各参数

[ root@CentOS ~]#awk  '{print ARGV[0]}' score2.txt 
awk
awk
awk
awk
awk
[ root@CentOS ~]#awk  '{print ARGV[1]}' score2.txt  
score2.txt
score2.txt
score2.txt
score2.txt
score2.txt
//"ARGV[0]":表示数组中的第一个元素,"ARGV[1]":表示数组中的第二个元素

BEGIN/END模式

BEGIN{}: 仅在开始处理文件中的文本之前执行一次

END{}:仅在文本处理完成之后执行一次

AWK自定义变量:

变量(区分字符大小写)
(1) -=value
(2) 在program中直接定义

[ root@CentOS ~]#awk -v test='hello word' 'BEGIN{print test}'
hello word
//定义test变量,并打印出来
[ root@CentOS ~]#awk  'BEGIN{test="hello word"; print test}'
hello word

printf命令:

格式化输出:printf “FORMAT”, item1, item2, ...
(1) 必须指定FORMAT
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT中需要分别为后面每个item指定格式符

格式符:需加"",与item一一对应

                          %c:显示字符的ASCII码(专门显示字符串)
                          %d,%i:显示十进制整数
                          %e,%E 科学技术法数值显示
                          %f:显示为浮点数
                          %g,%G:以科学计数法或浮点型式显示数值 
                          %s :显示字符串
                          %u :无符号整数
                          %% :显示%自身

修饰符

[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f

-: 左对齐(默认右对齐)%-15s
+:显示数值的正负符号%+d

[ root@CentOS ~]#awk  -F: '{printf  "%-10s" "%10d\n",$1,$3}' /etc/passwd
root               0
bin                1
daemon             2
adm                3
lp                 4
sync               5
shutdown           6
halt               7
mail               8
uucp              10
operator          11
games             12
gopher            13
ftp               14
nobody            99
vcsa              69
saslauth         499
postfix           89
sshd              74
admin1           500
// "%-10s" :向左对齐,s是字符串(一定要跟文件中内容一样,/etc/passwd/中的$1是字符串,$3是数字所以写的是 "%10d"),\n是换行
-----------------------------------------------------------------------------------------
[ root@CentOS ~]#awk  -F: '{printf  "NAME: %-10s  UID:%-10d\n",$1,$3}' /etc/passwd
NAME: root        UID:0         
NAME: bin         UID:1         
NAME: daemon      UID:2         
NAME: adm         UID:3         
NAME: lp          UID:4         
NAME: sync        UID:5         
NAME: shutdown    UID:6         
NAME: halt        UID:7         
NAME: mail        UID:8         
NAME: uucp        UID:10        
NAME: operator    UID:11        
NAME: games       UID:12        
NAME: gopher      UID:13        
NAME: ftp         UID:14        
NAME: nobody      UID:99        
NAME: vcsa        UID:69        
NAME: saslauth    UID:499       
NAME: postfix     UID:89        
NAME: sshd        UID:74        
NAME: admin1      UID:500 
//也可以添加一些字符串然看起来更美观点

操作符

算数操作符:
    x+y , x-y, x*y , x/y , x^y , x%y
    -x:整数转换成负数
    +:转换为数值
    字符串操作符:没有符号的操作符,字符串链接
    赋值操作符:
    =, +=, -= , *= , /= , %= ,^=
    比较操作符:
        >, >=, <, <=, !=, ==
    模式匹配符
        ~ :是否匹配
        !~:是否不匹配
    逻辑操作符:
        &&:并且
        ||:或者
        !:非
    条件表达式(三目表达式):
    selector?if-true-expression:if-false-expression 
//后面案例我们都会用到

awk PATTERN

(1)如果未指定:空模式,匹配每一行

(2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来

[ root@CentOS ~]#awk  '/^root/{print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
//显示以行首(^:行首的意思)为root的行

(3) relational expression:

关系表达式,结果为“真”才会被处理

真:结果为非0值,非空字符串

假:结果为空字符串或0值

[ root@CentOS ~]#awk  -F: '$3>200{print $1,$3}' /etc/passwd
saslauth 499
admin1 500
//匹配/etc/passwd中的$3,第三段是否大于200,如果大于就打印出来,否则不打印
[ root@CentOS ~]#awk  -F: '$NF=="/bin/bash"{print $NF}' /etc/passwd 
/bin/bash
/bin/bash
//$NF每行字段的最后一位字符串,如果匹配到的是 "/bin/bash"就打印出来

三目表达式:

[ root@CentOS ~]#awk -F: '{$3<500?user="is system":user="is common";{printf "%-10s %10s\n" ,$1,user}}' /etc/passwd
root        is system
bin         is system
daemon      is system
adm         is system
lp          is system
sync        is system
shutdown    is system
halt        is system
mail        is system
uucp        is system
operator    is system
games       is system
gopher      is system
ftp         is system
nobody      is system
vcsa        is system
saslauth    is system
postfix     is system
sshd        is system
admin1       is cmmon
//以":"分割,/etc/passwd中的第三行(uuid)小于500的就输出"is system ",否则就输入"is common",
//三目表达式格式:selector?if-true-expression:if-false-expression 

控制语句

if(condition) {statments}
if(condition) {statments} else {statments}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break 、continue 、delete arry[index] 、delete arry 、exit {statements}

if else 案例

[ root@CentOS ~]#awk  -F: '{if($3>=200) {printf "Common user: %-10s %8s\n",  $1,$3}else{printf "is system %-10s %10s\n",$1,$3}}' /etc/passwd
is system root                0
is system bin                 1
is system daemon              2
is system adm                 3
is system lp                  4
is system sync                5
is system shutdown            6
is system halt                7
is system mail                8
is system uucp               10
is system operator           11
is system games              12
is system gopher             13
is system ftp                14
is system nobody             99
is system vcsa               69
Common user: saslauth        499
is system postfix            89
is system sshd               74
Common user: admin1          500
// if判断$3(/etc/passwd中的id)>=200就打印"Common user: $1,$3",否则就打印小于200(/etc/passwd中id)小于200的用户和id("is system $1,$3")

while和for 循环

[ root@localhost ~]#awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) { if(length($i)>=3) {print $i,length($i)};i++}}' /etc/grub2.cfg 
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
crashkernel=auto 16
net.ifnames=0 13
linux16 7
/vmlinuz-0-rescue-e2b1c08415194abdb3672f06ea53672b 50
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
crashkernel=auto 16
net.ifnames=0 13

//对/etc/grub2.cfg进行操作,以行首为空白开头最少一次或者多次并且后面跟linux16的行(^[[:space:]]*linux16),"i=1;while(i<=NF)",NF(统计每行的字段),i小于等于每行的字段总数,
if(length($i)>=3:意思是每行的每段的字符串字数大于等于3的打印出来,最后的{print $i,length($i)};i++}}
意思是:打印$i就是每行的段,length($i):将次匹配到的字符串放入这里面,最后的i++每次i的值都会+1,从1一直加到小于等于每行的字段数(只匹配设定前面设定条件的行)
//length 字符串长度
-----------------------------------------------------------------------------------------------
[ root@localhost ~]#awk  '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++){ if(length($i)>=2) {print $i,length($i)}}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-514.el7.x86_64 30
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
ro 2
crashkernel=auto 16
net.ifnames=0 13
linux16 7
/vmlinuz-0-rescue-e2b1c08415194abdb3672f06ea53672b 50
root=UUID=25927f3c-9f12-45f7-8995-652b4468aebe 46
ro 2
crashkernel=auto 16
net.ifnames=0 13

//跟上面效果一样,只不过换成for循环

数组

[ root@CentOS ~]#awk 'BEGIN{user["w"]="wang";user["m"]="ma";print user["m"]}'   
ma
// 声明一个数组,[]里面声明了2个元素,元素和值必须加双引号,打印时也许要输入双引号
//注意:var会遍历array的每个索引
--------------------------------------------------------------------------------------------
[ root@CentOS ~]#awk  'BEGIN{user["w"]="wang";user["m"]="ma";for(i in user) {print user[i]}}'  
wang
ma
//通过for循环打印出数组中的元素
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • awk介绍awk变量printf命令:实现格式化输出操作符awk patternawk actionawk数组aw...
    哈喽别样阅读 1,549评论 0 4
  • 转载 原文的排版和内容都更加友好,并且详细,我只是在这里贴出了一部分留作自己以后参考和学习,如希望更详细了解AWK...
    XKirk阅读 3,188评论 2 25
  • 本章主要学习内容awk介绍 awk基本用法 awk变量 awk格式化 awk操作符 awk条件判断 a...
    楠人帮阅读 1,252评论 0 8
  • awk:报告生成器,格式化文本输出 内容: awk介绍 awk基本用法 awk变量 awk格式化 awk操作符 a...
    BossHuang阅读 1,451评论 0 9
  • awk: grep,sed,awk grep:文本过滤 sed:文本编辑 awk:文本格式化工具; 1 什么是aw...
    木林森阅读 1,764评论 0 16