awk

awk:报告生成器,格式化文本输出

内容

awk介绍

awk基本用法

awk变量

awk格式化

awk操作符

awk条件判断

awk循环

awk数组

awk函数

调用系统命令

注意: 字符串要用双引号引起来不然输入命令无效,或错误

基本用法:

awk[options]'program'var=valu file

awk[options]

-f programfilevar=value file…

awk[options]

'BEGIN{ action;… } pattern{ action;… } END{ action;… }' file ...

awk程序通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块,共3部分组成

program通常是被单引号或双引号中

选项:

-F指明输入时用到的字段分隔符

-v var=value:自定义变量

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

program:pattern{action

statements;......}

pattern:分决定动作语句何时触发及触发事件

action

stattements:对数据进行处理,放在{}内指明printprintf

分隔符、域和记录:

行可以叫记录

列可以叫---->域---->字段---->属性

啊我可执行时,由分割符分隔的字段(域)标记$1,$2..$n称为域标识。$0为所有域

注意:AWK和shell中变量¥符含义不同

文件的每一行称为记录

省略action ,则默认执行print $0

awk工作原理

第一步:执行BEGIN{action;… }语句块中的语句

第二步:从文件或标准输入(stdin)读取一行,然后执行pattern{ action;… }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

第三步:当读至输入流末尾时,执行END{action;…}语句块

BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中

END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是一个可选语句块

pattern语句块中的通用命令是最重要的部分,也是可选的。如果没有提供pattern语句块,则默认执行{ print },即打印每一个读取到的行,awk读取的每一行都会执行该语句块

print格式:printitem1,item2,...

要点:

(1)逗号为分隔符

(2)输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式

(3)如果省略|item,相当于print$0

tail  –3 /etc/fstab|awk‘{print $2,$4}’

计算用户UID总和:

awk

-F : '{sum+=$3}END{print sum}' /etc/passwd


图1


awk变量

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

awk-vFS=':''{print $1,FS,$3}'/etc/passwd(以:为分隔符取/etc/passwd第一第三字段)

awk–F:'{print $1,$3,$7}’ /etc/passwd

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

awk-v FS=‘:’ -v OFS=‘:’ '{print $1,$3,$7}’

/etc/passwd

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

awk -v RS=";"'{print $1,$3,$4}' f1(以分号为记录的分隔符,取记录的第1,3,4字段)


图2

ORS:输出记录分隔符,输出时用指定符号代替换行符

awk-vORS='##$#' {print $1,#$3,$4}f1

NF:字段数量

awk-F:'{print NF}'   /etc/fstab,引用内置变量不用$

awk-F: '{print $(NF-1)}'     /etc/passwd

NR:行号

awk    '{print NR}'   /etc/fstab(没有意义,只是输出行号)

awk   -F:'{print NF,$0}'    /etc/passwd(给/etcpasswd加入行号)

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

awk  '{printFNR}'  f1   test

图3

FILENAME:当前文件名

awk '{print FILENAME}’ /etc/fstab

ARGC:命令行参数的个数

awk  'BEGIN{print ARGC}'    /etc/fstab/etc/inttab

图4


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

awk   'BEGIN{print ARGV[0]}'f1test第一个参数为awk


图5

awk   'BEGIN{printARGV[1],ARGV[2]}'test f1  显示第二第三个参数


图6

awk   'BEGIN{printARGV[2]}'   test  f1

awk   'BEGIN{printARGV[ARGC-1]}'  test f1两都表示第三被参数


图7

ARGC-1=ARGV参数下标

awk变量

自定义变量(区分字符大小写)

(1) -v var=value

(2)在program中直接定义

示例:

awk  -v test='hello gawk'   '{print test}' /etc/fstab

awk  -v test='hello gawk'   'BEGIN{print test}'

awk  'BEGIN{test="hello,gawk";printtest}'

awk    –F:  '{sex=“male”;print$1,sex,age;age=18}'    /etc/passwd

cat   awk  script  {print script,$1,$2}

awk-F: -f awkscriptscript=“awk” /etc/passwd

printf命令:

格式化输出:printf"FORMAT",item1,item2

1)必须指定FORNAT(格式)

2 )不会自动换行,需要显式给出换行控制符,\n

3 ) FORMAT中需要分别为后面每个item指定格式符

4)FORMAT两边必须加上双引号

5)别忘了FORMAT与item1之间有一个逗号:"FORMAT",item1

格式符:与item一一对应

%c:显示字符的ASCII码

%d, %i:显示十进制整数

%e, %E:显示科学计数法数值

%f:显示为浮点数

%g, %G:以科学计数法或浮点形式显示数值

%s:显示字符串(常用)

%u:无符号整数

%%:显示%自身

修饰符:

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

-:左对齐(默认右对齐)%-15s

+:显示数值的正负符号%+d

printf例子:

awk  -F:   '{printf"%s",$1}'  /etc/passwd不会自动换行(不加换行符感觉很乱),需要显式给出换行控制符,\n

•awk  -F:  '{printf"%s\n",$1}'  /etc/passwd  加了换行符

初学者的错误:


图8

awk  -F:  '{printf "%-20s %10d\n",$1,$3}'    /etc/passwd


图9

•awk  -F:  '{printf "Username: "%s\n",$1}'   /etc/passwd("%s\n"与$1别忘了加逗号)

•awk-F:'{printf“Username: %s,UID:%d\n",$1,$3}'

/etc/passwd

•awk -F: '{printf"Username:  %15s,UID:%d\n",$1,$3}'  /etc/passwd


图10

注意:

写成自定义格式是不要把printf写成pint下面的就是这样的错误


图11


操作符

算术操作符:

x+y, x-y, x*y,

x/y, x^y, x%y

-x:转换为负数

+x:转换为数值

字符串操作符:没有符号的操作符,字符串连接

赋值操作符:

=, +=, -=, *=,

/=, %=, ^=

++, --

比较操作符:

==, !=,>,

>=, <, <=

模式匹配符:~:左边是否和右边匹配包含!~:是否不匹配

awk–F: '$0 ~ /root/{print $1}‘ /etc/passwd

awk'$0~“^root"' /etc/passwd

awk'$0 !~ /root/‘ /etc/passwd

awk–F: ‘$3==0’ /etc/passwd

操作符

逻辑操作符:与&&,或||,非!

示例:

•awk –F:  '$3>=0 && $3<=1000 {print $1}' /etc/passwd

•awk -F: '$3==0  || $3>=1000 {print $1}' /etc/passwd

•awk -F: '!($3==0){print $1}' /etc/passwd

•awk -F:  '!($3>=500) {print $3}'  /etc/passwd

函数调用:function_name(argu1, argu2, ...)

条件表达式(三目表达式):

selector?if-true-expression:if-false-expression

逻辑:如果selector成立执行if-true-exprssione的内容,否则执行:if-false-expression的内容。?与:为固定格式造抄

示例:用awk显示/etc/passwd中的系统用户和普通用户

awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or

SysUser";printf"%-15s:%-s\n",$1,usertype}' /etc/passwd

...

图12


图12 续


PATTERN:根据pattern条件,过滤行,在处理

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

awk   '/^UUID/{print $1}'  /etc/fstab

awk   '!/^UUID/{print $1}'  /etc/fstab

3) relational expression:关系表达式,结果为“真”才会被处理

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

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

1)如果没有指定:为空模式,匹配每一行(可以理解成4后面的描述)

4)如果PATTERN没有{action},说明省略{print $0},表示输出匹配到的整行(记录)如下:

awk  -F: 'i=1;j=1{printi,j}'/etc/passwdi=1后面省略了{print $0}所以先输出整行,在输出i,j的值


图14

awk '!0'/etc/passwd!0为1,1表示匹配整行,没有动作{action}表示输出整行,连起来表示输出整行


图15


awk  -F:  '$3>=500{print $1,$3}'  /etc/passwd$3为用户UID表示$3>500表示用户UID大于500 ,print #$1,$3表示输出$1(用户名)$3(用户UId)


图16

awk -F: '$NF== "/bin/bash"{print $1,$NF}'  /etc/passwdNF表示字段数,$NF表示最后一个字段 ,当$NF(最后的字段)等于/bin/bash时,执行后面的动作它等价于

awk -F: '$NF ~/bash$/{print#$1,$NF}'/etc/passwd/bash$/是正则表达式


图17

4.4) line  ranges:行范围

startline,endline:/pat1/,/pat2/不支持直接给出数字格式

awk -F:  '/^root\>/,/^nobody\>/{print $1}'   /etc/passwd

awk-F:  '(NR>=10&&NR<=20){print NR,$1}' /etc/passwd


BEGIN/END模式

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

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

示例:

awk -F : 'BEGIN {print "USER USERID"} {print

$1":"$3} END{print "end file"}' /etc/passwd

•awk -F : '{print "USER USERID“;print $1":"$3}  END{print "end file"}' /etc/passwd

•awk -F: 'BEGIN{print " USER UID \n---------------"}{print $1,$3}' /etc/passwd

awk -F: 'BEGIN{print" USER UID \n---------------"}{print $1,$3}END{print "=============="}'/etc/passwd

.............................................................

seq 10 |awk ‘i=0’i=0为假不符合条件,不执行

seq 10 |awk ‘i=1’i=1为真,符合条件,执行动作没有指定:为空模式,匹配每一行

seq 10 | awk 'i=!i‘因为i没有赋值所以i=0当i=0是!0为1,1为真 执行输出为1,执行过后i=1,!i为0,0为假不执行,此时i=0,!i=1执行,当i=1时!i=0,不执行

seq 10 | awk '{i=!i;print i}‘为命令seq 10 | awk 'i=!i‘中i的值

seq 10 | awk '!(i=!i)'因为i没有赋值所以i=0当i=0是!0为1,!(i=1)为0不执行,过后i=1

(i=!1)i=0, !(i=0)为1,执行...

•seq 10 |awk -v i=1 'i=!i'i=1,赋值初始化,只执行一次,i=!1 ,i=0,为假,不执行,i=0,i=!0,i=1,为真执行,。。。

awk控制语句

if-else

if-else语法:if(condition){statement;...}[else statement]

if(condition1){statement;...}else

if (condition2){statement2}else {statement3}


图17


图17续

seq10 |awk ‘i=0’i=0为假不符合条件,不执行


图1-1

seq 10 |awk 'i=1'  i=1为真,符合条件,执行动作没有指定:为空模式,匹配每一行


图1-2

seq 10 | awk 'i=!i‘因为i没有赋值所以i=0当i=0是!0为1,1为真 执行输出为1,执行过后i=1,!i为0,0为假不执行,此时i=0,!i=1执行,当i=1时!i=0,不执行


图1-4


seq 10 | awk '{i=!i;print i}‘为命令seq 10 | awk 'i=!i‘中i的值


图1-5

seq 10 | awk '!(i=!i)'因为i没有赋值所以i=0当i=0是!0为1,!(i=1)为0不执行,过后i=1

(i=!1)i=0, !(i=0)为1,执行...


图1-7

•seq 10 |awk -v i=1 'i=!i'i=1,赋值初始化,只执行一次,i=!1 ,i=0,为假,不执行,i=0,i=!0,i=1,为真执行,。。。


图1-8


awk控制语句:

if-else

if-else语法:if(condition){statement;...}[else statement]

if(condition1){statement;...}else

if (condition2){statement2}else {statement3}

使用场景:对awk取的整行或某个字段做条件判断

awk  -F: '{if($3>=1000)print $1,$3}'  /etc/passwd  

awk  -F: '{if($NF=="/bin/bash") print $1}'  /etc/passwd

awk'{if(NF>5) print $0}' /etc/fstab

awk-F: '{if($3>=1000) {printf"Common user:

%s\n",$1} else {printf"root or Sysuser: %s\n",$1}}' /etc/passwd

awk -F: '{if($3>=1000) printf "Common user:

%s\n",$1;

else printf "root or Sysuser: %s\n",$1}'

/etc/passwd

df -h|awk-F% '/^\/dev/{print

$1}'|awk'$NF>=80{print $1,$5}‘

awk'BEGIN{ test=100;if(test>90){print "very

good"}

else if(test>60){ print

"good"}else{print "no pass"}}'


while循环

语法:while(condition){statement;}

条件“真”,进入循环;条件“假”,退出循环

使用场景:

对一行内的多个字段逐一类似处理时使用

对数组中的个元素逐一处理使用

示例:

awk'/^[[:space:]]*linux16/{i=1;while(i<=NF)

{print $i,length($i); i++}}' /etc/grub2.cfg

awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=10)

{print $i,length($i)}; i++}}' /etc/grub2.cfg

do-while循环

语法:do {statement;…}while(condition)

意义:无论真假,至少执行一次循环体

示例:

•awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print

total}‘


for循环

语法:for(expr1;expr2;expr3) {statement;…}

常见用法:

for(variable assignment;condition;iterationprocess)

{for-body}

特殊用法:能够遍历数组中的元素

语法:for(varin array) {for-body}

示例:

awk'/^[[:space:]]*linux16/{for(i=1;i<=NF;i++)

{print $i,length($i)}}' /etc/grub2.cfg

性能比较

time (awk 'BEGIN{

total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')

time(total=0;for i in {1..10000};do

total=$(($total+i));done;echo $total)

time(for ((i=0;i<=10000;i++));do let

total+=i;done;echo $total)

time(seq –s ”+” 10000|bc)


图20

awk控制语句

switch语句

语法:switch(expression)

{case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2;

...; default: statementn}

break和continue

•awk  'BEGIN {sum=0;for(i=1;i<=100;i++)

{if(i==66)break;sum+=i,}

print sum}

awk控制语句

break [n]

continue [n]

next:

提前结束对本行处理而直接进入下一行处理(awk自身循环)

awk -F: '{if($3%2!=0) next; print $1,$3}'  /etc/passwd


awk数组

关联数组:array[index-expression]

index-expression:

•(1)可使用任意字符串;字符串要使用双引号括起来

•(2)如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”

若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历

示例:

•weekdays[“mon”]="Monday“

•awk

'BEGIN{weekdays["mon"]="Monday";

weekdays["tue"]="Tuesday";print

weekdays["mon"]}‘

•awk ‘!arr[$0]++’ dupfile

•awk '{!arr[$0]++;print $0, arr[$0]}' dupfile

awk数组

若要遍历数组中的每个元素,要使用for循环

for(varinarray) {for-body}

注意:var会遍历array的每个索引

示例:

•awk'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]

="Tuesday";for(iin weekdays) {print

weekdays[i]}}‘

•netstat-tan | awk'/^tcp/{state[$NF]++}END

{for(i in state) { print i,state[i]}}'

•awk'{ip[$1]++}END{for(iin ip) {print i,ip[i]}}'

/var/log/httpd/access_log

for(变量in阵列)

如:

awk -F : '{line[$7]++}END{for(i in line){ print i,line[i]}}' /etc/passwd

其中因为line[$7]没有赋值默认为0,遍历中i代表数组line的下标为$7,line[i]为为line[$7]为次数


图21


awk '/^tcp/{line[$NF]++}END{for(i in line){printi,line[i]}}'  f1.log

netstat -nt | awk -F '[[:space:]:]+''/^tcp/{ip[$6]++}END{for(i in ip){printi,ip[i]}}'

netstat -nt|awk -F '[[:space:]:]+''/^tcp/{ip[$6]++}END{for(i in ip){printi,ip[i]}}' |sort -nr -k2 |awk '{print $1}'|head -10

netstat -tn | awk  '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'

awk '{total[$3]+=$2;num[$3]++}END{for(name intotal){print name,total[name],total[name]/num[name]}}' score.txt

数值处理:

rand():返回0和1之间一个随机数

awk'BEGIN{srand(); for (i=1;i<=10;i++)print

int(rand()*100) }'

直接写随机数是错误的,它需要种子srand()才能生成随机数

字符串处理:

•length([s]):返回指定字符串的长度

•sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s

echo "2008:08:08 08:08:08" | awk'sub(/:/,“-",$1)'

•gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容

echo "2008:08:08 08:08:08" |

awk‘gsub(/:/,“-",$0)'

•split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,…

netstat-tan |

awk  '/^tcp\>/{split($5,ip,":");count[ip[1]]++}

END{for (iin count) {print i,count[i]}}'


system命令

空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。

awk BEGIN'{system("hostname") }'

awk'BEGIN{score=100; system("echo your score is

" score) }'

将awk程序写成脚本,直接调用或执行

示例:

#cat f1.awk

{if($3>=1000)print $1,$3}

#awk-F: -f f1.awk /etc/passwd

#cat f2.awk

#!/bin/awk–f

#this is a awkscript

{if($3>=1000)print $1,$3}

#chmod+x f2.awk

#f2.awk –F: /etc/passwd


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 本章主要学习内容awk介绍 awk基本用法 awk变量 awk格式化 awk操作符 awk条件判断 a...
    楠人帮阅读 1,214评论 0 8
  • awk介绍awk变量printf命令:实现格式化输出操作符awk patternawk actionawk数组aw...
    哈喽别样阅读 1,486评论 0 4
  • awk: grep,sed,awk grep:文本过滤 sed:文本编辑 awk:文本格式化工具; 1 什么是aw...
    木林森阅读 1,697评论 0 16
  • awk命令的基本使用 [root@shellscript ~]# head -n 3 /etc/passwd | ...
    古寒飞阅读 1,040评论 0 2
  • '#Gun awk的相关用法 awk的工作原理 一次读取一行文本,按输入分隔符进行切片,切成多个组成部分,将每片直...
    魏镇坪阅读 39,232评论 2 37