写点什么

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

评论

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

OmniPlan Pro 4 for Mac v4.8.1中文激活版:项目管理的新选择

iMac小白

OmniPlan Pro 4下载 OmniPlan Pro 4破解版

高效云端管理的秘诀——华为云命令行工具KooCLI

轶天下事

企业数字化转型,人才是关键。华为政企咨询如何赋能客户高效培养数字化人才?

轶天下事

香港云服务器

百度搜索:蓝易云

云服务器 香港服务器 海外服务器 高防服务器 免备案服务器

带你了解GaussDB SQL中的BOOLEAN表达式

华为云开发者联盟

数据库 华为云 华为云GaussDB 华为云开发者联盟 企业号2024年5月PK榜

如何通过分散原则保证系统高可用

京东零售技术

架构 高可用 后端 企业号 5 月 PK 榜

产业互联网助力预制菜出海 云创科技数据资产入表获批融资500万 新能源装备新质供应链创新协同平台启动 | 产业互联网观察第173期

AMT企源

华为 阿里 产业互联网 数字化转型 AMT企源

联手火山引擎,华硕利用大模型和向量数据库推出AI功能笔记本

新消费日报

阅读架构整洁之道

追随月光的战士

git密码正确还提示git Permission denied, please try again.

百度搜索:蓝易云

git 云计算 Linux 运维 云服务器

如何在Ubuntu 20.04|18.04上安装FreeSwitch

百度搜索:蓝易云

云计算 Linux 运维 云服务器 高防服务器

httpsok-v1.11.0支持CDN证书自动部署

物有本末

https CDN 免费SSL证书 HTTPSOK nginx证书

华为云发布CodeArts API,为API护航

平平无奇爱好科技

云原生中间件最新动态24年3月 - 分布式消息队列服务DMS

轶天下事

阅读架构整洁之道

追随月光的战士

华为云开发者桌面全新发布CodeArts IDE for Python,极致优雅云原生开发体验

轶天下事

软件开发生产线CodeArts 3月新特性上线啦!

轶天下事

在Ubuntu安装RPM文件

梦笔生花

ubuntu 系统 内核 uboot

《编译原理》阅读笔记:p4-p17

codists

编译原理

Docker容器没有ip addr命令:exec ip addr报错

百度搜索:蓝易云

Docker 云计算 运维 IP 云服务器

🔥架构师狂掉1024根头发,总算搞定SSL通配证书

物有本末

https SSL证书 ssl HTTPSOK nginx证书

Metes and Bounds Pro for Mac:精准数据转换与绘图利器

iMac小白

Metes and Bounds Pro Metes and Bounds Pro下载

华为云FunctionGraph构建高可用系统的实践

平平无奇爱好科技

centos7更新podman

百度搜索:蓝易云

Linux centos 运维 云服务器 Podman

ChatGPT无需注册就能使用!为何突然“免费”?

蓉蓉

openai ChatGPT4

A-CSPO课程概念澄清和实操:假定(Assumptions)、实验(Experiments)、假设(Hypotheses)

ShineScrum捷行

高阶产品开发 敏捷产品

🔥httpsok-v1.11.0支持OSS证书自动部署

物有本末

https OSS 证书管理 免费SSL证书 HTTPSOK

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