前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux之awk命令详解(二)

Linux之awk命令详解(二)

作者头像
AsiaYe
发布2019-11-06 16:49:47
2.6K1
发布2019-11-06 16:49:47
举报
文章被收录于专栏:DBA随笔DBA随笔
Linux之awk命令详解(二)

上一篇文章我们简单举了几个例子了解了一下awk命令的基本语法,这里,再次贴出来这个命令的基本语法,如下:

awk基本语法:

awk [option] 'pattern{action}' file1,file2,...filen

其中action中最常用的print命令。通过上一篇文章我们知道option当中包含的是awk命令的一些参数,pattern当中包含的BEGIN和END等awk模块,action当中包含的是awk命令当中的动作,这篇文章介绍awk的其他一些特征。

01

awk脚本

awk命令也经常用来写一些脚本,这些脚本的格式如下:

代码语言:javascript
复制
脚本格式
awk 'BEGIN{ commands } pattern{ commands } END{ commands }' file 

下面简单介绍下awk执行脚本的过程:

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

下面我们来看一个awk脚本的例子:

代码语言:javascript
复制
[root@dev01 yeyz_shell]# vim score.txt
[root@dev01 yeyz_shell]# cat score.txt 
Marry      
Jack       
Tom        
Mike       
Bob        
[root@dev01 yeyz_shell]# vim awk.txt
[root@dev01 yeyz_shell]# cat awk.txt 
#!/bin/awk -f
#运行前
BEGIN {
    math = 
    english = 
    computer = 

    printf "NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL\n"
    printf "---------------------------------------------\n"
}
#运行中
{
    math+=$3
    english+=$4
    computer+=$5
    printf "%-6s %-6s %4d %8d %8d %8d\n", $1, $2, $3,$4,$5, $3+$4+$5
}
#运行后
END {
    printf "---------------------------------------------\n"
    printf "  TOTAL:%10d %8d %8d \n", math, english, computer
    printf "AVERAGE:%10.2f %8.2f %8.2f\n", math/NR, english/NR, computer/NR
}

[root@dev01 yeyz_shell]# awk -f awk.txt score.txt
NAME    NO.   MATH  ENGLISH  COMPUTER   TOTAL
---------------------------------------------
Marry                           
Jack                            
Tom                             
Mike                            
Bob                             
---------------------------------------------
  TOTAL:                    
AVERAGE:     63.80    78.60    70.00
[root@dev01 yeyz_shell]# 

上面的例子中,我们首先构造一个数据源文件score.txt,然后定义一个awk脚本awk.txt文件,这个脚本给源文件首尾都加上了一些标志,这些标志当中使用格式控制符对输出的格式进行控制,最终输出结果如上代码段所示。

02

格式化输出

上面的脚本当中使用了诸如%10d等格式化输出的符号,这里我们对这些符号进行一定的解释,格式化输出的时候,一般使用printf函数,而不是print方法,这里我们看一种格式化输出方法:

代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test5.txt 
aaa bbb ccc
xxx yyy zzz
uuu vvv www
[root@dev01 yeyz_shell]# awk  '{printf "第一列: %s\n",$1}' awk_test5.txt 
第一列: aaa
第一列: xxx
第一列: uuu
[root@dev01 yeyz_shell]# awk  '{printf "第一列: %s 第二列 : %s\n",$1,$2}' awk_test5.txt 
第一列: aaa 第二列 : bbb
第一列: xxx 第二列 : yyy
第一列: uuu 第二列 : vvv
[root@dev01 yeyz_shell]# 

03

pattern模式详解

awk命令中的pattern模式不仅仅有BEGIN和END两种,还有一些其他的模式,这里举例子进行说明:

代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test6.txt 
 this is line 
 this is line 
 this is line 
 this is line 
 this is line 

打印出行号等于的行
[root@dev01 yeyz_shell]# cat awk_test6.txt | awk 'NR==5{print $0}'
 this is line 

打印出行号大于的行
[root@dev01 yeyz_shell]# cat awk_test6.txt | awk 'NR>3{print $0}'
 this is line 
 this is line 

打印出第一列是的行
[root@dev01 yeyz_shell]# cat awk_test6.txt | awk '$1==3{print $0}'
 this is line 

通过上述例子我们可以看到,awk命令中的模式可以写成一些条件表达式,例如NR==5,NR>3,$1==3等等,如果我们在模式处不写任何东西,那就变成了我们最常用的那种awk '{print $1,$2}',这种类型的语句我们也可以任务它有模式,只不过它的模式是空而已。至此,我们见过的模式包含以下三种:

空模式

BEGIN/END模式

条件表达式模式

接下来,介绍另外一种模式,即正则模式,正则模式跟正则表达式有一定的关系,正则模式下的awk命令的语法如下:

awk ‘/正则表达式/{print $0}’ filename

话不多说,我们还是通过例子来看。

代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test7.txt 
hello,word
this is a shell program
This is a handsome boy
I am a DBA

找出包含and的行,并打印它的第一列
[root@dev01 yeyz_shell]# cat awk_test7.txt | awk '/and/{print $1 }'
This

找出包含a的行,并打印它的第一列
[root@dev01 yeyz_shell]# cat awk_test7.txt | awk '/a/{print $1 }'
this
This
I

上面的例子描述了如何通过正则匹配出包含某个关键字的行,并打印这一行的某一列值,当然,有一些例子存在例外,比如下面这个:

代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test8.txt 
/usr/local/mysql
/bin/bash
/etc/profile
[root@dev01 yeyz_shell]# cat awk_test8.txt | awk '//bin/bash/{print $1}'
awk: //bin/bash/{print $1}
awk:            ^ syntax error
[root@dev01 yeyz_shell]# cat awk_test8.txt | awk '/\/bin\/bash/{print $1}'
/bin/bash
[root@dev01 yeyz_shell]#

当我们使用/bin/bash来匹配的时候,我们发现语法报错,原因是这个文件中包含的都是路径,而带/的字符串匹配的时候会和正则表达式前后的/产生冲突,也就是/正则表达式/这种格式中,正则表达式中不能出现/,如果出现,需要使用\/进行转义。

正则匹配模式还包含很多,没有办法全部罗列,后续有应用的时候再去查询吧,常用的一些方法记住就足够应对一般的应用场景了。

04

条件语句

了解了匹配模式,现在我们再来看看条件语句。条件语句,顾名思义就是在awk命令中加入if else这种条件判断语句,具体怎么去加,我们还是通过例子来看:

代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test9.txt 
hello  world
good good study
I love you very much
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if(NR="hello"){print $2}}'
world
good
love

如果某一行第一列是hello,则输出该行第二列的值
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if($1=="hello"){print $2}}'
world

如果某一行第一列是hello,则输出该行第二列的值,否则输出该行的所有列
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if(NR==3){print $2} else {print $0}}'
hello  world
good good study
love

输出第三行的第二列
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if(NR==3){print $2}}'
love

05

内置函数

awk中包含很多内置函数,这些内置函数如果使用的比较熟练,可以有很大的作用,这里简单列举几个内置函数的用法:

substr函数

代码语言:javascript
复制
substr(s,p)     返回字符串s中从p开始的后缀部分
substr(s,p,n)   返回字符串s中从p开始长度为n的后缀部分
代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test9.txt 
hello  world
good good study
I love you very much

拿到第一行的字符串
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if(NR==1){print $0}}'
hello  world

拿到第一行的字符串,然后打印第二列第三个字母开始到字符串末尾 world-->rld
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if(NR==1){print $0}}' | awk '{print substr($2,3)}'
rld

拿到第一行的字符串,然后打印第二列第三个字母开始,连续打印两个字符 world-->rl
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{if(NR==1){print $0}}' | awk '{print substr($2,3,2)}'
rl

split 分割函数

split是一个分割函数,它的基本用法是:

split (string, array, field separator) split (string, array) -->如果第三个参数没有提供,awk就默认使用当前FS值

代码语言:javascript
复制
[root@dev01 yeyz_shell]# var="10:11:12"
[root@dev01 yeyz_shell]# echo $var | awk '{split($0,a,":");print a[1],a[2],a[3]}'
  

length函数

输出文本的长度,举例如下:

代码语言:javascript
复制
echo "123" | awk '{print length}'

[root@dev01 yeyz_shell]# cat awk_test9.txt 
hello  world
good good study
I love you very much

输出每一行的长度
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{print length}'




输出每一行第一列单词的长度
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '{print length($1)}'



gsub替换函数

gsub函数则使得在所有正则表达式被匹配的时候都发生替换。它的基本语法为: gsub(src, dst, target string); 简称 gsub(r,s,t)。

代码语言:javascript
复制
[root@dev01 yeyz_shell]# cat awk_test9.txt 
hello  world
good good study
I love you very much

将文本中所有包含good的列当中的good改为bad
[root@dev01 yeyz_shell]# cat awk_test9.txt | awk '$0 ~ /good/ {gsub("good", "bad", $0); print $0}'
bad bad study
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 DBA随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档