文本编辑三剑客(awk)

awk作为和sed、grep同级的文本处理命令,也又强大的文本分析功能,同样,它的原理并不困难,但操作很多且很杂,可以通过不同的需求进行自定义搭配。

awk工作原理

awk和另外两个命令的工作原理又不相同,当用户输入命令时,awk从标准输入或输入文件、命令行参数中读取数据,按照用户定义的模式进行匹配,匹配成功则执行相应操作,然后将结果输出到标准输出或指定的文件中

awk 提供了三个特殊的模式,BEGIN、pattern、END

BEGIN 块在任何输入数据处理之前执行,通常用于初始化变量、设置字段分隔符、打印头信息等

pattern 块在每条记录被读取后执行,如果记录与模式匹配,则执行相应的动作

END 块在所有输入数据处理完毕后执行,通常用于打印汇总信息、关闭文件等

所以,我们可以将awk工作的流程简单地分为三个步骤:

读:从文件、管道、标准输入等中读入一行然后将其放入到内存中

执行:根据命令按序执行,默认是处理每一行,可指定需求

重复:处理完当前记录后,awk继续读取下一条记录,并重复执行上述步骤,直到所有记录都被处理完

命令格式

原理只是辅助理解,最重要的还是能灵活使用命令

awk 的命令格式是  

awk [选项]  模式或条件{操作} 文件

awk -f 脚本文件  文件

awk  关键字  选项  命令部分 '{xxxx}'  文件名

awk 支持内置变量和自定义变量

常见的内置变量有

FS:指定字段的分隔符,默认为空格或制表符

NF:当前正在处理的行的字段数,有的时候也用作表示列的个数

NR:当前处理的行的行号

$0:当前处理的行的整行

$n:当前处理行的第n个字段

FNR:各文件分别计数的行号

OFS:输出字段分隔符

ORS:输出记录分隔符

RS:记录行分隔符

案例

首先来点简单的,我们打印出第一列,就用/etc/passwd文件吧,将他拷贝到/opt目录下,方便操作,又不会对原文件产生影响

awk -F : '{print $1}' passwd               -F 指定分隔符是必须要的,不指定分隔符啥也打不出来,

                                                           passwd文件每列之间的分隔符也确实  ":"

按照规则来,便能输出你想要的结果

同时打印一二两列,并且中间用 - - 隔开 ↓

如果中间要间隔一个制表符也是可以的,将 - - 换成 \t

有的时候,一个文件里并不只是以一个符号隔开的,可能前面是: 后面还穿插着/等之类的其他分隔符,这时候我们进行筛选的时候就需要设定两个分隔符

awk -F [:/] '{print $5 "- -"$8}' passwd          还以passwd文件为例,假如有另外一个分隔符/ 

照我们这样的分法,第一行打印出来的应该是 root 和空白,因为第八列恰好在 : 和 / 之间

 我们来验证结果

事实亦是如此

简单的打印操作差不多就是这样,接下来我们要用到上面说到的那些什么 FS NR NF等内置变量

打印出含有数字的行的第一列,并显示行号

awk -F: '/[0-9]/{print NR"--"$1}' passwd               NR显示行号,和实际内容之间也是用--隔开了

结果验证无误,若想要打印出含有数字的行的这一整行,我们就不需要特别指定$几列,改成$0即可,如果什么都不加,那将会只打印行号

接着,我现在想看看,passwd文件里每一行究竟有多少列,那假如 / 也算分隔符,那又有多少列?

awk -F: '{print NF}' passwd                                 awk -F[:/] '{print NF}' passwd 

看看前几行就差不多了,就不截全了,可以看到,每行有多少列被统计了出来,因为passwd本身并没有以/为分隔符,所以第二个命令打印出来的数字参差不齐,因为路径不一样

如果嫌麻烦不想查看有多少列,就想直接打印最后一列,那么我们的列号就直接改成 $NF就可以了

行号也可以指定,比如打印第一行第一列

awk -F: 'NR==1 {print $1}' passwd

应用到实际案例中

还是以网卡为例,要求直接输出 本机的ip地址是:

ifconfig ens33 | awk '/netmask/{print "本机的IP地址是:"$2}'    

因为我们首先要筛选出含有ip地址的那一行(独有netmask的那一行,其实也可以根据自己的理解设定其他筛选条件),随后再输出ip地址所在的列

awk也可以像sed 还有 grep 那样,匹配查询一些特定的字符,比如,查找含有 root 的行

awk -F: '/root/' passwd 


awk -F: '$1~/ro/' /etc/passwd   模糊查询,查询第一列含有ro的行

如果想要查找不含ro的行,就在 ~ 号前面加一个!表示不包含

我们还可以通过用字符串来实现查找功能,只不过这个查找就是比较精确的了,输入什么字符就精确匹配什么字符,比如查找最后一列是/bin/bash的

 awk -F: '$7=="/bin/bash"' passwd    一定要加双引号,格式要正确,这样才能成功查找

我也是输了很多次发现格式有问题,最终加了双引号,加了/ 才查找成功

既然 = 号都出现了,那么 > 或者 < 应该也不意外,用法也如它们本身的含义一样,比如passwd文件里,第三列基本上都是数字,那我们就可以查找,第三列大于1000的行

不仅如此,逻辑符号也可以一并加入使用,第三列大于1000,并且小于1005

两条符合查询条件的结果被输出了出来,当然不仅可以只对数字的大小做要求,字符类型其他列等,都可以加入查询条件,具体按照什么规则来查询,就看自己的发挥了

awk同样可以选择输出偶数行还是奇数行  ,getline 读取数据时,得到的是下一行

seq 10 | awk '{getline;print $0}'    显示偶数行

seq 10 | awk '{print $0;getline}'    显示奇数行

前面提到FS、OFS、FNR 等内置变量,其实理解起来也非常简单

FS:指定字段的分隔符,默认为空格或制表符

如,我们要在在打印之前定义字段分隔符为冒号,打印第三行

awk 'BEGIN{FS=":"}{print $3}' passwd              这里BEGIN 就是在打印前做

FNR:追加行号

awk '{print FNR,$0}' passwd   就可以看到输出的内容的行号

OFS:输出字段分隔符

awk 'BEGIN{FS=":";OFS="- -"}'      这个结果的输出命令就和之前

awk -F [:/] '{print $5 "- -"$8}' passwd 输出效果一样,我就不演示了

ORS:输出记录分隔符

awk 'BEGIN{ORS=" "}{print $0}' passwd  

把多行合并成一行 输出,输出的时候自定义以空格分隔每行,默认是回车键

RS:记录行分隔符

awk 'BEGIN{RS=":"}{print $0}' /etc/passwd    

指定以什么为换行符,这里指定是冒号,指定的肯定是原文里存在的字符


awk 拥有一个特殊的功能,那就是可以加入条件判断语句或者循环语句等

awk if语句

还是passwd文件,比如,如果第三列大于1000,那就打印第三列,否则打印第一列

awk -F: '{if($3>1000){print $3}else{print $1}}'  passwd

因为文件里的行数太多,我就不截全了,逻辑上来说,排除用户名就是数字的,输出结果中,应该全是大于1000的数字,如果不是数字,那就都是passwd文件中的用户名

awk数组

看到数组会觉得头疼吗?还好,awk里的数组目前用不到十分困难的,我们只需要会如何定义如何输出就好了

awk 'BEGIN{a[0]=10;a[1]=20;print a[1]}'           定义了a[0] a[1] 并打印a[1]

相应的,打印a[0] 输出结果肯定就是10了

awk 'BEGIN{a["abc"]=10;a["xyz"]=20;print a["abc"]}'        和上面一个意思

awk循环

上面的数组定义完,我们就可以插入循环啦

awk 'BEGIN{a[0]=10;a[1]=20;a[2]=30;for(i in a){print i,a[i]}}'      定义一个数组,再让i对应数组元素,并进行打印

awk '{line[NR] = $1} END{for(i in line){print "Line " i ":" line[i]}}' xslx.txt

 将每一行的第一个字段存储在数组 line 中,使用行号 NR 作为索引,然后用for循环遍历数组,并打印每个元素及其索引

awk 的用法基本上就这么多,然后至此文本编辑三剑客的讲解也就圆满结束了,功能很多,所以东西也很多很杂,多敲多练熟稔于心

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值