写点什么

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:061170

评论

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

云图说丨初识华为云OrgID:轻松实现统一帐号、统一授权

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 7 月 PK 榜

语雀 × 支付宝小程序云:发布技术干货,赢语雀会员和周边!

TRaaS

文档写作 #程序员

PoseiSwap 即将开启质押,利好刺激下 POSE通证短时涨超 30%

BlockChain先知

信创产业未来发展如何

小齐写代码

ChatGPT下程序员应该何去何从?

小魏写代码

ChatGPT 新手用ChatGPT

软件测试/测试开发丨Python 内置库 文件处理 学习笔记分享

测试人

Python 程序员 软件测试 文件处理 内置库

和鲸 ModelWhale 与海光适配认证,“国产 CPU +开发平台” 双轮驱动信创生态建设及 AI 产业应用

ModelWhale

cpu 数字化转型 信创 数据科学 信创产业

企业做数字化转型,请先避开这5个坑!

优秀

数字化转型

低代码:告别繁琐,提速软件开发

互联网工科生

软件开发 低代码 数字化

IDC公布2022中国大数据平台私有化部署市场份额,柏睿数据位列第一梯队

新消费日报

ChatGPT下程序员应该何去何从?

小齐写代码

DWS轻量化更新黑科技:宽表加工优化

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 7 月 PK 榜

2023 数字生态发展大会,和鲸 ModelWhale 入选中国信通院“铸基计划”《高质量数字化转型产品及服务全景图》

ModelWhale

数字化转型 中国信通院 铸基计划

MobTech秒验,一键登录快人一步!

MobTech袤博科技

前端 App 免密登录 登录验证 秒验

JMeter 查看 TPS 数据

Liam

程序员 测试 Jmeter 测试工具 TPS

大模型时代,企业如何重构 AI 应用落地范式?

Fabarta

Flink 实践教程:入门(11):MongoDB Sink 的使用

腾讯云大数据

流计算 Oceanus

什么样的程序员在35岁后仍然保持竞争力?

互联网工科生

程序员 技术 持续学习 经验

国内常见的16款低代码开发平台介绍

优秀

低代码开发平台 低代码平台 企业级低代码平台

全球视频编码领域顶级大赛放榜,网易云信首次参赛即斩获H.265赛道多项指标第一

网易智企

音视频技术 H.265

英伟达 H100 vs. 苹果M2,大模型训练,哪款性价比更高?

GPU算力

新版安卓iOS双端语音派对聊天APP源码开发核心功能和开发要点介绍

山东布谷科技胡月

语音聊天APP源码 视频语音直播app开发 语音社交APP搭建 语音房APP开发 语音厅源码

AI算力爆发,新职业出现,你发现了吗?

小齐写代码

信创产业未来发展如何

小魏写代码

信创 信创产业

建设数字工厂:生产订单批量拆分的实现方法

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 7 月 PK 榜

新鲜出炉!Go薪资最高,JS需求量最大!

树上有只程序猿

Java c++ Python 编程语言

对线面试官 - HashMap

派大星

HashMap底层原理 Java 面试题

人人都有大模型用!大模型ChatGLM2-6B新手速通!

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨 百度飞桨

全球视频编码领域顶级大赛放榜,网易云信首次参赛即斩获H.265赛道多项指标第一

网易云信

音视频 H.265 音视频通话

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