Shell:awk文本处理工具,Linux的SQL神器(一篇搞定awk)

Shell:awk文本处理工具,Linux的SQL神器(一篇搞定awk)关键词 Linux Shell awk 内容摘要 awk 简介 awk 语法快速开始 awk 命令参数设置 awk 设置变量正则匹配过滤 pattern match 条件判断过滤 类比 SQLaction 操作语法 类比 SQLawk 任务实战 awk 简介 awk 是一个强大

欢迎大家来到IT世界,在知识的湖畔探索吧!

关键词:LinuxShellawk

内容摘要

  • awk简介
  • awk语法快速开始
  • awk命令参数设置
  • awk设置变量
  • 正则匹配过滤pattern,match
  • 条件判断过滤,类比SQL
  • action操作语法,类比SQL
  • awk任务实战

awk简介

awk是一个强大的文本分析工具,尤其是对linux中的结构化二维表数据可以实现类似SQL的检索,统计,替换功能。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理,是一种能够完成文本遍历正则匹配逻辑判断结果操作的shell代码集合,使得开发者能够更方便地在linux上进行文件操作

  • 功能支持:文本匹配,文本转化,文本统计分析
  • 操作对象:文件或者标准输入
  • 工作方式:逐行扫描`文件,从第一行到最后一行,执行匹配和操作逻辑

awk语法快速开始 

awk基本语法如下

  • awk ‘pattern’ filename
  • awk ‘{action}’ filename
  • awk ‘pattern {action}’ filename

其中pattern代表匹配条件,action代表对目标内容进行的操作,filename代表文件,其中filename(或者标准输入输出)必不可少,pattern和action二者必须有其中一个,否则无法运行。一共支持三种方式,表明awk支持仅文件内容匹配仅文件内容操作先匹配指定文件内容再做操作三种模式,下面对这三种模式进行快速上手

1.仅文件内容匹配

若awk没有设置action操作,则action默认是print,即将匹配到的内容进行打印输出。比如使用正则匹配出/etc/group文件中存在docker字符的整行,匹配某个完整字符的pattern语法是/pattern/

awk '/docker/' /etc/group docker:x:999:

欢迎大家来到IT世界,在知识的湖畔探索吧!

另一种是条件过滤匹配,例如精确匹配第一个元素为docker的行,精确匹配需要对匹配内容加双引号,用双等于==进行判断

欢迎大家来到IT世界,在知识的湖畔探索吧!awk 'BEGIN{FS=":"}$1=="docker"' /etc/group docker:x:999,test

其中BEGIN{}代表该句awk的处理前逻辑,在该例的作用是设置全局变量FS分隔符为冒号,$1是被分割后每行的第一个元素,索引从1开始,$0代表整行

2.仅文件内容操作

若awk没有设置匹配条件则不做任何筛选拿到全部内容,此时操作是针对全部内容比如一个文件的所有行,默认操作是打印匹配到的内容,也可以自定义操作,比如打印分隔后的第一个元素而不是整行

awk 'BEGIN{FS=":"}{print $1}' /etc/group sambashare mysql docker

3.先匹配指定文件内容再做操作

pattern和action结合先筛选出符合的行再做统一操作,例如筛选包含docker的行输出第一个元素

欢迎大家来到IT世界,在知识的湖畔探索吧!awk 'BEGIN{FS=":"}/docker/{print $1}' /etc/group docker

4.对标准输出进行操作

可以对标准输出做awk操作,产生标准输出的方式有catecho等,以及可以在控制台输出的工具,例如使用cat的输出

cat /etc/group |awk 'BEGIN{FS=":"}{print $1}' root daemon bin sys adm

使用echo的输出取出空格分隔后的第二个元素

echo "1 2 3 4" |awk '{print $2}' 2

使用其他命令到控制台的输出,比如docker images命令的输出筛选镜像

docker images | awk '/mysql/' mysql 5.7 09361feeb475 5 months ago 447MB mysql latest 5c62e459e087 5 months ago 556MB

awk命令参数设置

在上一节中已经介绍了awk的简单用法和作用,本节详细看下awk可以设置的参数,常用参数如下

命令选项

描述

-F

指定文本分隔符,默认是Tab或者空格

-v

在复杂逻辑中设置变量

‘ ‘

引用代码块

-f

-f或者-file,从脚本文件中读取awk命令

BEGIN

初始化代码块,在每一行处理之前运行,设置处理逻辑的全全局变量

END

结尾代码块,在每一行处理完之后再执行,输出最终的计算结果

{}

代码块,编写处理逻辑,BEGIN和END后面也需要{}

对其中几个进行测试,-F文本问个符号

echo "1,2,3,4" |awk -F "," '{print $2}' 2

BEGIN用于在awk匹配逻辑之前设置全局变量,必须大写例如设置内置分隔符为冒号

awk 'BEGIN{FS=":"}{print $1}' /etc/group

也可以设置自定义变量,变量的命名由用户自定义,如果有多个变量中间用分号;隔开,在引用的时候action中直接引用变量名(不加$)

awk 'BEGIN{FS=":";v1="用户组是"}{print v1$1}' /etc/group 用户组是mysql 用户组是docker

该例设置了自定义变量v1,赋值为字符串“用户组是”,在action中引用进行格式化打印

-v设置awk全局变量,可以在action中引用设置的变量,效果和在BEGIN中设置一样

awk -v v1="用户组是:" -v v2=" gid是" 'BEGIN{FS=":"}{print v1$1v2$2}' /etc/group 用户组是:mysql gid是xxx 用户组是:docker gid是xxx

END用于在遍历完每一行后进行一个计算操作,最终得出全部计算结果,例如统计总共遍历了多少行

awk 'BEGIN{FS=":";cnt=0}{cnt+=1}END{print cnt}' /etc/group 71

该例中先自定义了一个变量cnt=0,action操作每遍历一行cnt+=1,这个和cat /etc/group |wc -l结果一致

awk设置变量

对于awk来说变量又分为内置变量自定义变量,awk中包含很多内置变量,比如说-F命令默认的分隔符是Tab或者空格,实际上就是awk的内部变量FS来控制的,内置变量的目的是在awk代码中进行修改和引用,常用的内置变量如下

变量名

描述

$0

当前记录,整个一行记录

$1~$n

当前记录被分隔符分割之后的元素,根据索引位置排

FS

字段分隔符 默认是空格

NF

字段个数,就是有多少列

NR

行号,从1开始

RS

记录之间的分隔符,默认是换行符

FILENAME

当前输入文件的名字

IGNORECASE

如果为真,则进行忽略大小写的匹配

NF输出分隔后字段个数

echo '1 2 3 4' |awk '{print NF}' 4

NR显示行号,比如选取70行以上的

awk 'BEGIN{FS=":"}NR>70{print $0}' /etc/group test:x:1001:

复杂一点取偶数行,直接拿到NR计算即可

awk 'BEGIN{FS=":"}NR%2==0{print $0}' /etc/group

IGNORECASE忽略大小写,比如用在精确匹配中大写匹配规则可以匹配小写内容

awk 'BEGIN{FS=":";IGNORECASE=1}$1=="Docker"{print $0}' /etc/group docker:x:999:test

具体是将IGNORECASE加入BEGIN中,1是开启,0是关闭,默认关闭

正则匹配过滤pattern,match

pattern部分支持正则表达式的语法,比如以下案例加入了正则表达式的元素

^符号匹配行首,比如查看ls的是文件夹的,以d开头

ll |awk /^d/ drwxr-xr-x 5 root root 4096 12月 9 17:25 ./ drwxr-xr-x 62 root root 4096 12月 13 14:36 ../ drwxr-xr-x 4 root root 4096 7月 29 18:48 bisai/ drwxrwxr-x 2 root root 4096 2月 20 2019 docker/

$匹配结尾,匹配以f结尾的行

echo -e "dsd\nsdslhf\nssdf\n" |awk '/f$/' sdslhf ssdf

[ ]匹配字符集,可以完成多个字符集中任何一个字符的匹配,比如匹配以d或者s开头的并且第二个字符是s的结果

echo -e "dsd\nkdslhf\nssdf\n" |awk '/^[ds]s/' dsd ssdf

[^ ]排他设置,和字符集匹配相反,只要不在指定的字符集内其他的都算匹配到,比如匹配首字母不是k和s的所有行

echo -e "dsd\nkdslhf\nssdf\n" |awk '/^[^ks]/' dsd

match函数:macth可以返回指定要匹配内容,类似通用的正则表达式,格式如下

match($0,/pattern/,a);action

在match函数中$0代表对整行进行匹配,对ip地址进行匹配,匹配结果赋值到变量a,在action阶段拿到a匹配到的指定内容

ifconfig wlp2s0|grep netmask |awk '{match($0,/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/,a); print a[1]}' 192.168.43.59

条件判断过滤

条件过滤部分可以实现单分之和多分支逻辑,类似于SQL的Where语句,语法如下

awk 'BEGIN{}条件{action}END{}'

例如统计每行第三个字段姓名是小王的行数,相当于SQL的select count… where…

awk '$3=="小王"{i++}END{print i}' info.txt 21

其中$3==”小王是条件放在最前面,{i++}是action初始的变量i为0,最后调用print打印出统计值,在这个基础上再增加一个条件,第四列学历是小学的,相当于select count… where…and…

awk '$3=="工商"&&$4=="小学"{i++}END{print i}' info.txt 6

使用&&完成条件的交集,同理并集使用||,代表或的逻辑。也可以完成检索展示的工作,例如检索A列姓名等于某值时B列分数的值

awk '$3=="小王"{print $2}' info.txt 33 22 12

action操作语法

action对每一行过滤后的结构进行操作,除了打印,还可以在这一步完成统计分析的逻辑编写,比如实现select sum的功能,对一列累加求和

awk -F "," '{sum+=$2}END{print sum}' score.txt 1315

使用action可以实现类似SQL group by的功能,分组统计个数,类似于select count(1) group by,比如

awk '{x[$3]+=1}END{for(i in x){print i,x[i]}}' score.txt 语文 5 数学 1 英语 21 

实现的方式是在action中定义一个关联数组x,然后往里面添加key和+1,在END中再遍历一次即可,如果不使用awk而是写shell定义数组和遍历需要很长一段,如下

#/bin/bash unset x declare -A x while read line do key=`echo $line |awk -F ' ' '{print $3}'` x[$key]=$[${x[$key]}+1] done<score.txt for i in ${!x[@]} do echo $i,${x[$i]} done

在action里面可以加入条件筛选,相当于action也可以包含pattern的功能,比如统计出每行第三个字段是语文的行数,相当于SQL的select count …where…

awk '{if($3=="语文")i++}END{print i}' score.txt 10

再加一个分之判断,统计一下语文和数学,多个判断条件之间要用;分号隔开,如果不用分号需要将条件判断后面的代码加{}代码段

awk '{if($3=="语文") i++; else if($3=="数学") j++;}END{print i,j}' score.txt 21 10

同样还可以完成SQL的判断输出任务,相当于case when

awk '{if($3=="语文")print "数据源是语文"; else if($3=="数学")print "数据源是数学"; else print "数据源是其他"}' score.txt 数据源是其他 数据源是语文 数据源是数学 数据源是其他

实际上action可以一步到位,将条件和操作全部写在action里面,多条件分之注意在else,else if之前增加分号

awk任务实战

一个常用的任务是从配置文件中获取某个key的value,传入Shell脚本中进行处理,例如有这样一个yml文件

cat config.yml mysql_host: 172.17.0.1 mysql_port: 3306 mysql_user: aaa mysql_password: 

现要从中获取其中的mysql_host

awk -F ':' '$1=="mysql_host"{gsub(" ","",$0);print $2}' config.yml 172.17.0.1

其中gsub用来替换空格,顺序为先调用gsub去除空格,在使用-F进行分割,再判断$1==”mysql_host。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/81410.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们YX

mu99908888

在线咨询: 微信交谈

邮件:itzsgw@126.com

工作时间:时刻准备着!

关注微信