QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

Linux 三剑客之 awk(3):awk 数组与语法

  • 2020-02-10
  • 本文字数:4621 字

    阅读完需:约 15 分钟

Linux三剑客之awk(3):awk数组与语法

一、awk 数组

1.1 数组结构

1560825858603035163.png


people[police]=110


people[doctor]=120


[root@creditease awk]# awk 'BEGIN{word[0]="credit";word[1]="easy";print word[0],word[1]}'  credit easy  [root@creditease awk]# awk 'BEGIN{word[0]="credit";word[1]="easy";for(i in word)print word[i]}'  credit  easy  
复制代码

1.2 数组分类

索 引数组:以数字为下标


关联数组:以字符串为下标

1.3 awk 关联数组

现有如下文本,格式如下:即左边是随机字母,右边是随机数字, 即将相同的字母后面的数字加在一起,按字母的顺序输出


a  1  b  3  c  2  d  7  b  5  a  3   g  2  f  6  
复制代码


1]=a[2(a[2)然后配合 END 和 for 循环输出结果:


[root@creditease awk]# awk '{a[$1]=a[$1]+$2}END{for(i in a)print i,a[i]}' jia.txt   a 4  b 8  c 2  d 7  f 6  g 2  注意:for(i in a) 循环的顺序不是按照文本内容的顺序来处理的,排序可以在命令后加sort排序  
复制代码

1.4 awk 索引数组

以数字为下标的数组 seq 生成 1-10 的数字,要求只显示计数行


[root@creditease awk]# seq 10|awk '{a[NR]=$0}END{for(i=1;i<=NR;i+=2){print a[i]}}'  1  3  5  7  9  
复制代码


seq 生成 1-10 的数字,要求不显示文件的后 3 行


[root@creditease awk]# seq 10|awk '{a[NR]=$0}END{for(i=1;i<=NR-3;i++){print a[i]}}'  1  2  3  4  5  6  7  解析:改变i的范围即可,多用于不显示文件的后几行  
复制代码

1.5 awk 数组实战去重

a++ 和 ++a


[root@creditease awk]# awk 'BEGIN{print a++}'  0  [root@creditease awk]# awk 'BEGIN{print ++a}'  1  [root@creditease awk]# awk 'BEGIN{a=1;b=a++;print a,b}'  2 1  [root@creditease awk]# awk 'BEGIN{a=1;b=++a;print a,b}'  2 2  
注:
都是 b = a+1
b=a++ 先把 a 的值赋予b,然后 a + 1
b=++a 先执行a+1,然后把a的值赋予b
复制代码


对一下文本进行去重处理 针对第二列去重


[root@creditease awk]# cat qc.txt   2018/10/20   xiaoli     13373305025  2018/10/25   xiaowang   17712215986  2018/11/01   xiaoliu    18615517895   2018/11/12   xiaoli     13373305025  2018/11/19   xiaozhao   15512013263  2018/11/26   xiaoliu    18615517895  2018/12/01   xiaoma     16965564525  2018/12/09   xiaowang   17712215986  2018/11/24   xiaozhao   15512013263  
复制代码


解法一:  [root@creditease awk]# awk '!a[$2]++' qc.txt   2018/10/20   xiaoli     13373305025  2018/10/25   xiaowang   17712215986  2018/11/01   xiaoliu    18615517895   2018/11/19   xiaozhao   15512013263  2018/12/01   xiaoma     16965564525  解析:  !a[$3]++是模式(条件),命令也可写成awk '!  a[$3]=a[$3]+1{print $0}' qc.txt  a[$3]++ ,“++”在后,先取值后加一  !a[$3]=a[$3]+1:是先取a[$3]的值,比较“!a[$3]”是否符合条件(条件非0),后加1  注意:此方法去重后的结果显示的是文本开头开始的所有不重复的行  解法二:  [root@creditease awk]# awk '++a[$2]==1' qc.txt   2018/10/20   xiaoli     13373305025  2018/10/25   xiaowang   17712215986  2018/11/01   xiaoliu    18615517895   2018/11/19   xiaozhao   15512013263  2018/12/01   xiaoma     16965564525  解析:  ++a[$3]==1是模式(条件),也可写成a[$3]=a[$3]+1==1即只有当条件(a[$3]+1的结果)为1的时候才打印出内容  ++a[$3] ,“++”在前,先加一后取值  ++a[$3]==1:是先加1,后取a[$3]的值,比较“++a[$3]”是否符合条件(值为1)  注意:此方法去重后的结果显示的是文本开头开始的所有不重复的行  解法三:  [root@creditease awk]# awk '{a[$2]=$0}END{for(i in a){print a[i]}}' qc.txt  2018/11/12   xiaoli     13373305025  2018/11/26   xiaoliu    18615517895  2018/12/01   xiaoma     16965564525  2018/12/09   xiaowang   17712215986  2018/11/24   xiaozhao   15512013263  
解析: 注意此方法去重后的结果显示的是文本结尾开始的所有不重复的行
复制代码

1.6 awk 处理多个文件(数组、NR、FNR)

使用 awk 取 file.txt 的第一列和 file1.txt 的第二列然后重定向到一个新文件 new.txt 中


[root@creditease awk]# cat file1.txt   a b  c d  e f  g h  i j  [root@creditease awk]# cat file2.txt   1 2  3 4  5 6  7 8  9 10  [root@creditease awk]# awk 'NR==FNR{a[FNR]=$1}NR!=FNR{print a[FNR],$2}' file1.txt file2.txt   a 2  c 4  e 6  g 8  i 10  解析:NR==FNR处理的是第一个文件,NR!=FNR处理的是第二个文件.  注意:当两个文件NR(行数)不同的时候,需要把行数多的放前边.  解决方法:把行数多的文件放前边,行数少的文件放后边.  把输出的结果放入一个新文件new.txt中:  [root@creditease awk]# awk 'NR==FNR{a[FNR]=$1}NR!=FNR{print a[FNR],$2>"new.txt"}' file1.txt file2.txt   [root@creditease awk]# cat new.txt   a 2  c 4  e 6  g 8  i 10  
复制代码

1.7 awk 分析日志文件,统计访问网站的个数

[root@creditease awk]# cat url.txt   http://www.baidu.com  http://mp4.video.cn  http://www.qq.com  http://www.listeneasy.com  http://mp3.music.com  http://www.qq.com  http://www.qq.com  http://www.listeneasy.com  http://www.listeneasy.com  http://mp4.video.cn  http://mp3.music.com  http://www.baidu.com  http://www.baidu.com  http://www.baidu.com  http://www.baidu.com  [root@creditease awk]# awk -F "[/]+" '{h[$2]++}END{for(i in h) print i,h[i]}' url.txt  www.qq.com 3  www.baidu.com 5  mp4.video.cn 2  mp3.music.com 2  www.crediteasy.com 3  
复制代码

二、awk 简单语法

2.1 函数 sub gsub

替换功能


格式:sub(r, s ,目标) gsub(r, s ,目标)


[root@creditease awk]# cat sub.txt   ABC DEF AHI GKL$123  BAC DEF AHI GKL$213  CBA DEF GHI GKL$321  [root@creditease awk]# awk '{sub(/A/,"a");print $0}' sub.txt   aBC DEF AHI GKL$123  BaC DEF AHI GKL$213  CBa DEF GHI GKL$321  [root@creditease awk]# awk '{gsub(/A/,"a");print $0}' sub.txt   aBC DEF aHI GKL$123  BaC DEF aHI GKL$213  CBa DEF GHI GKL$321  注:sub只会替换行内匹配的第一次内容;相当于sed ‘s###’      gsub 会替换行内匹配的所有内容;相当于sed ‘s###g’  [root@creditease awk]# awk '{sub(/A/,"a",$1);print $0}' sub.txt   aBC DEF AHI GKL$123  BaC DEF AHI GKL$213  CBa DEF GHI GKL$321  
复制代码


练习:


0001|20081223efskjfdj|EREADFASDLKJCV  0002|20081208djfksdaa|JDKFJALSDJFsddf  0003|20081208efskjfdj|EREADFASDLKJCV  0004|20081211djfksdaa1234|JDKFJALSDJFsddf  以'|'为分隔, 现要将第二个域字母前的数字去掉,其他地方都不变, 输出为:  0001|efskjfdj|EREADFASDLKJCV  0002|djfksdaa|JDKFJALSDJFsddf  0003|efskjfdj|EREADFASDLKJCV  0004|djfksdaa1234|JDKFJALSDJFsddf  
方法: awk -F '|' 'BEGIN{OFS="|"}{sub(/[0-9]+/,"",$2);print $0}' sub_hm.txt awk -F '|' -v OFS="|" '{sub(/[0-9]+/,"",$2);print $0}' sub_hm.txt
复制代码

2.2 if 和 slse 的用法

内容:


AA


BC


AA


CB


CC


AA


结果:


AA YES


BC NO YES


AA YES


CB NO YES


CC NO YES


AA YES


1) [root@creditease awk]# awk '{if($0~/AA/){print $0" YES"}else{print $0" NO YES"}}' ifelse.txt   AA YES  BC NO YES  AA YES  CB NO YES  CC NO YES  AA YES  解析:使用if和else,if $0匹配到AA,则打印$0 "YES",else反之打印$0 " NO YES"。  2)[root@creditease awk]# awk '$0~/AA/{print $0" YES"}$0!~/AA/{print $0" NO YES"}' ifelse.txt   AA YES  BC NO YES  AA YES  CB NO YES  CC NO YES  AA YES  解析:使用正则匹配,当$0匹配AA时,打印出YES,反之,打印出“NO YES”  
复制代码

2.3 next 用法

如上题,用 next 来实现


next :跳过它后边的所有代码


 [root@creditease awk]# awk '$0~/AA/{print $0" YES";next}{print $0" NO YES"}' ifelse.txt   AA YES  BC NO YES  AA YES  CB NO YES  CC NO YES  AA YES  解析:  {print $0" NO YES"}:此动作是默认执行的,当前边的$0~/AA/匹配,就会执行{print $0" YES";next}  因为action中有next,所以会跳过后边的action。  如果符合$0~/AA/则打印YES ,遇到next后,后边的动作不执行;如果不符合$0~/AA/,会执行next后边的动作;  next前边的(模式匹配),后边的就不执行,前边的不执行(模式不匹配),后边的就执行。  
复制代码

2.4 printf 不换行输出以及 next 用法

printf :打印后不换行


如下文本,如果 Description:之后为空,将其后一行内容并入此行。


Packages: Hello-1  Owner: me me me me  Other: who care?  Description:  Hello world!  Other2: don't care  想要结果:  Packages: Hello-1  Owner: me me me me  Other: who care?  Description: Hello world!  Origial-Owner: me me me me  Other2: don't care  1)[root@creditease awk]# awk '/^Desc.*:$/{printf $0}!/Desc.*:$/{print $0}' printf.txt   Packages: Hello-1  Owner: me me me me  Other: who care?  Description:Hello world!  Other2: don't care  解析:使用正则匹配,匹配到'/^Desc.*:$/,就使用printf打印(不换行),不匹配的打印出整行。  2)使用if和else实现  [root@creditease awk]# awk '{if(/Des.*:$/){printf $0}else{print $0}}' printf.txt   Packages: Hello-1  Owner: me me me me  Other: who care?  Description:Hello world!  Other2: don't care  3)使用next实现  [root@creditease awk]# awk '/Desc.*:$/{printf $0;next}{print $0}' printf.txt   Packages: Hello-1  Owner: me me me me  Other: who care?  Description:Hello world!  Other2: don't care  注:可简写成awk '/Desc.*:$/{printf $0;next}1'  printf.txt  ## 1是pattern(模式),默认action(动作)是{print $0}  
复制代码

2.5 去重后计数按要求重定向到指定文件

文本如下,要求计算出每项重复的个数,然后把重复次数大于 2 的放入 gt2.txt 文件中,把重复次数小于等于 2 的放入 le2.txt 文件中


[root@creditease files]# cat qcjs.txt   aaa  bbb  ccc  aaa  ddd  bbb  rrr  ttt  ccc  eee  ddd  rrr  bbb  rrr  bbb  [root@creditease awk]# awk '{a[$1]++}END{for(i in a){if(a[i]>2){print i,a[i]>"gt2.txt"}else{print i,a[i]>"le2.txt"}}}' qcjs.txt   [root@creditease awk]# cat gt2.txt   rrr 3  bbb 4  [root@creditease awk]# cat le2.txt   aaa 2  ccc 2  eee 1  ttt 1  ddd 2  解析:{print },或括号中打印后可直接重定向到一个新文件,文件名用双引号引起来。如: {print $1 >"xin.txt"}  
复制代码

三、awk 需注意事项

a)NR==FNR ##不能写成 NR=FNR(=在 awk 中是赋值的意思)


b)NR!=FNR ##NR 不等于 FNR


c){a=1;a[NR]} 这样会报错:同一条命令中变量和数组名不能重复 d)printf 输出的时候不换行


e){print },或括号中打印后可直接重定向到一个新文件,文件名用双引号引起来。如: {print $1 >“xin.txt”}


f)当模式(条件)是 0 的时候,后边的动作不执行,!0 的时候后边动作才执行。


本文转载自宜信技术学院网站。


原文链接:http://college.creditease.cn/detail/262


2020-02-10 21:061054

评论

发布
暂无评论
发现更多内容

为什么Spring Boot项目加上就可以更新版本?

冉然学Java

程序员 源码分析 springboot Java 分布式 Java core

兆骑科创创业大赛,双创服务平台,线上直播路演

兆骑科创凤阁

快速定位线上慢SQL问题,掌握这几个性能排查工具可助你一臂之力

IT学习日记

MySQL性能优化 数据库优化 MySQL 数据库 签约计划第三季 explain关键字

开源一夏 | 阿里云物联网平台之极速体验

六月的雨在InfoQ

阿里云 开源 物联网 8月月更

豆瓣评分9.0,“Linux命令行”经典巨著升级版上市了!

图灵教育

高性能创作本,日常修图剪辑选华硕无畏Pro15 2022完全足矣!

科技热闻

手摸手带你完成智慧路灯构建及避坑【华为云至简致远】

神奇视野

Python 科技

技术干货|如何将 Pulsar 数据快速且无缝接入 Apache Doris

SelectDB

数据库 Doris pulsar 数据导入 kafaka

不可忽略!户外LED显示屏的特点及优势

Dylan

LED显示屏 户外LED显示屏 led显示屏厂家

【实战】Next.js + 云函数开发一个面试刷题网站

狂奔滴小马

Serverless React

彻底搞懂云桌面配置及实践踩坑【华为云至简致远】

神奇视野

Python 科技

开源一夏 |我在滴滴做开源

石臻臻的杂货铺

开源 8月月更

带你了解什么是 Web3.0

liuzhen007

Web 3.0

详谈RDMA技术原理和三种实现方式

C++后台开发

网络协议 C/C++后台开发 C/C++开发 RDMA技术 以太网

R7 6800H+RTX3050+120Hz 2.8K OLED屏,无畏Pro15 2022开启预售

科技热闻

阿里云 EMAS Serverless 升级发布

移动研发平台EMAS

小程序云开发 阿里云 Serverless 开发者 云开发

云硬盘EVS详解以及如何用与避坑【华为云至简致远】

神奇视野

Python 后端 云服务 科技

交大医学院临床研究中心如何将 ModelWhale 应用于临床医生教学、研究丨数据科学 x 临床医学

ModelWhale

人才培养 数据科学 低代码平台 教学 临床医学

破解数字化转型困局,企业分析协同场景案例解析

ModelWhale

数据分析 数字化转型 构建模型 成功案例 协同软件

出海季,互联网出海锦囊之本地化

融云 RongCloud

元宇宙 IT业界

可复现、开放科研、跨学科合作:数据驱动下的科研趋势及应用方案

ModelWhale

数据分析 代码复现 开放生态 协同软件 科研成果

2022最新发布超全的Java面试八股文,整整1700页,太全了

Java工程师

Java 面试 八股文

NFT盲盒挖矿DAO智能合约dapp系统开发详情

开发微hkkf5566

生物统计师与临床医生协同研究使用的低代码洞察平台丨数据科学 x 临床医学

ModelWhale

团队协作 Jupyter Notebook 数据科学 低代码开发 临床医学

一次做数据报表的踩坑经历,让我领略了数据同步增量和全量的区别

百思不得小赵

数据同步 增量同步 全量同步 签约计划第三季 8月月更

开源一夏 | 打工人的第25天-曾经的考研人

Amazing_eve

#开源

ModelWhale 云端运行 WRF 中尺度数值气象模式,随时随地即开即用的一体化工作流

ModelWhale

数据科学 气象 全流程一体化 WRF 大气科学

DeepLink在转转的实践

转转技术团队

ios android 客户端

使用前端技术实现静态图片局部流动效果

dragonir

CSS JavaScript html 前端 SVG

利用java实现视频人像分割及视频背景替换

夏夜许游

Java 图像分割 视频人像分割 背景替换

2021年数据泄露成本报告解读

SEAL安全

DevSecOps 数据安全 混合云 零信任 软件供应链

Linux三剑客之awk(3):awk数组与语法_开源_秦伟_InfoQ精选文章