- A+
在本博客中,AWK是一个系列文章,本人会尽量以通俗易懂的方式递进的总结awk命令的相关知识点。
awk系列博文直达链接:AWK命令总结之从放弃到入门(通俗易懂,快进来看)
这篇文章中的知识点是建立在前文的基础上的,如果你还没有掌握前文中的知识,请先参考之前的文章。
这篇文章其实是对之前知识点的拾遗,有些遗漏的常用知识点会在这篇文章中介绍。
三元运算
还记的我们在学习awk的 "if..else" 结构时,举的例子吗?我们来回顾一下。
在centos6中,我们可以判断用户的UID是否小于500,如果用户的UID大于500,则用户为普通用户,如果用户的UID小于500,则用户为系统用户。
所以,我们可以通过awk的 "if...else结构",判断用户的UID范围,从而判断出用户属于哪种用户类型,示例如下
正如上图所示,我们使用"if...else"结构,对usertype变量进行了赋值,如果用户的UID小于500,则对usertype变量赋值为"系统用户",否则则赋值usertype变量为"普通用户",最后打印出用户名所在的列与usertype变量的值。
其实,我们可以使用三元运算,替换上例中的"if...else"结构语句,示例如下
正如上图所示,红线标注部分则使用了三元运算的语法,代替了之前"if...else"的语法,而三元运算的语法如下:
条件 ? 结果1 : 结果2
上述语法表示,如果条件成立,则返回结果1,如果条件不成立,则返回结果2。
而上例中,"$3<500"就是上述语法中的"条件","系统用户"就是上述语法中"?"后面的"结果1","普通用户"就是上述语法中":"后面的"结果2" ,同时,在上例中我们使用usertype变量接收了三元运算后的返回值,所以,当条件成立时,usertype变量被赋值为"系统用户",当条件不成立时,usertype变量被赋值为"普通用户"。
是不是很方便?其实,三元运算还有另外一种使用方式,示例如下
我们通过上述命令,统计出了,系统用户有42个,普通用户有7个,上图中红线标注的用法可以理解为三元运算的另一种语法。如下
表达式1 ? 表达式2 : 表达式3
上述语法表示,如果表达式1为真,则执行表达式2,如果表达式1为假,则执行表达式3
而上例中,"$3<500"即为表达式1,"a++"即为表达式2,"b++"即为表达式3
也就是说,当每遇到一个UID小于500的用户,我就对变量a加1,否则我就对变量b加1,从而算出了系统用户与普通用户的数量,最后再END模式中输出了变量a与变量b的值。
是不是很容易理解?你一定已经明白了。
打印奇偶行
如果我们想要使用awk打印文本中的奇数行或者偶数行,则是非常简单的。
我们先来看看怎样使用awk打印奇数行或偶数行,然后再结合示例解释原理,所以看不懂没关系,后面会有解释。
正如上图所示,test12文件中有11行文本,我们可以使用非常简洁的awk命令,打印出了奇数行或者偶数行。
但是如果我们想要彻底搞明白原理,则需要搞明白如下两个知识点(后面会有更详细的解释)
1、在awk中,如果省略了模式对应的动作,当前行满足模式时,默认动作为打印整行,即{print $0}。
2、在awk中,0或者空字符串表示"假",非0值或者非空字符串表示"真"
上述两个知识点是什么意思呢?我们慢慢聊。
在之前介绍awk模式的文章中提及过,模式可以理解为条件,如果当前行能与模式匹配,则会执行对应的动作。示例如下
上图中的两个命令均使用到了模式
第一个命令表示如果当前行中包含字符"1",则执行对应的动作,而对应的动作就是打印整行。
第二个命令表示如果test12文本中文本行的第二列的值如果大于10,则执行对应的动作,而对应的动作就是打印整行。
那么,如果我们将上例中awk命令中的动作都省略,会出现什么情况呢?我们来试试。
我们发现,当使用了模式时,如果省略了对应的动作,会默认的输出整行。
也就是说,当使用了模式时,如果省略了模式对应的动作,默认动作为"{print $0}"
当然,"空模式"与"BEGIN/END模式"除外。
这就是第1个知识点的含义,我想你应该明白了,那么我们来聊聊第2个知识点。
在awk中,0或者空字符串表示"假",非0值或者非空字符串表示"真",什么意思呢?我们还是可以从模式说起,"模式"可以理解为"条件",当条件成立,则为真,当条件不成立,则为假,所以,当模式为真时,则会执行对应的动作,当模式为假时,则不会执行对应的动作。
那么,我们能不能直接把模式替换为"真"或者"假"呢?我们来试试。
上例中,命令1使用了"空模式",也就是说,每一行都满足模式,每一行经过"空模式"匹配以后结果都是"真",所以每一行都会执行对应的动作。
命令2中,原来"模式的位置"被替换为了数字"1",我们可以把数字"1"理解成一种模式匹配后的结果,而1是非零值,刚才说过,在awk中非零值表示真,所以,"1"表示"真", 换句话说就是模式的匹配结果为真,模式成立则会执行对应的动作,而命令2中,对应的动作为打印整行。
命令3 与 命令2 同理,在命令3中, 数字"2"为非零值,表示真,可以理解为:模式的匹配结果为真,则会执行对应的动作,聪明如你一定想到了,数值"2"可以换做任何非0值或者非空字符串。
命令4中,数字"2"为非零值,表示模式为真,而之前说过,当使用模式时,可以省略动作,当使用模式并省略动作时,默认动作为打印整行,所以,命令4表示打印所有行,因为每一行的模式都为真。
命令5与命令6同理,在awk中,数字"0"与空字符串表示假,当模式为假时,不会执行对应的动作,而当存在模式并省略动作时,默认动作为打印整行,但是由于模式为假,所以对应的动作并未执行。
其实,我们还能对真与假进行取反,非真即为假,非假即为真,示例如下。
正如上图所示,我们使用"!"对真假进行取反。
如果你已经看懂了上面的例子,那么,我们再来延伸一下。
你猜猜,如下示例会输出什么?
没错,聪明如你一定想到了,上例中,其实是使用了awk的变量,将变量 i 赋值为1,当 i=1 以后,i为非零值,表示为真,我们可以认为这是一种模式匹配后的结果,当模式为真时,同时省略了对应动作时,默认动作为打印整行,所以上例会输出test3中的所有行。
理解完上述示例以后,我们再回过头来,看看之前打印奇数行的示例,你可能就会明白了。
当awk开始处理第一行时,变量 i 被初始化,变量 i 在被初始化时,值为"空",而awk中,数字0或者"空字符串"表示假,所以可以认为模式为假,但是 i 直接取反了,对假取反后的值为真,将取反后的值又赋值给了变量i,此刻,变量i的值为真,所以当awk处理第一行文本时,变量i的值被赋值为真,模式成立则需要执行对应的动作,而上例中又省略了动作,所以默认动作为"{print $0}",所以,第一行被整行打印了。
当第一行文本处理完毕后,awk开始处理第二行文本,此时,i 为真,但是取反后,i 为假,所以第二行没有被输出,依次类推,最终只打印了奇数行。
为了能够更加直观的看到上述过程,我们将i的值打印出来,通过如下动作,能够打印出处理每一行时,i 对应的值。
当然,聪明如你,我就不用再解释打印偶数行的原理了,我想你应该已经能够举一反三了。
好了,这篇文章就写到这里,希望能够对你有所帮助~客官常来呦~~~

2020年5月30日 下午4:48 沙发
一天看完了博主的awk,受益匪浅,算是入门了吧。后续还要回来复习巩固
2020年7月5日 上午2:51 1层
@运维小白 一天?我都快看半年了还没掌握

2020年4月26日 下午8:37 板凳
无语了,,,朱老师真棒.
2020年1月7日 下午8:09 地板
博主你的留言板怎么会把代码搞乱呢!而且还会自动丢掉一些数据!!!
2020年1月7日 下午7:53 4楼
看完博主的文章(真是写的太好了)自己也乘热打铁写了一个脚本(统计):
#!/bin/bash
#by author Gan
file=tes.csv
awk_shaw(){
awk -v FS=’,’ ‘BEGIN{printf “%-38s%-10s%-20s%-20s%-20s%-10s\n”,” Projects”,”Number”,”Average”,”Sum”,”Max”,”Min”}’
for ((i=2;i1{sum+=$n;{if(NR==2){los=$n}}{if(los>$n){los=$n}};{max>$n?max=max:max=$n}}{lev=NR-1}END{printf “%-38s%-10d%-20f%-20f%-20f%-20f\n”,begin,lev,a=sum/lev,sum,max,los}’ $file
#echo $i
done
}
awk_shaw
2019年12月20日 上午11:44 5楼
都是九年义务教育,为何这么优秀,看完还想看一遍.
2019年12月19日 下午9:01 6楼
楼主讲得很清楚,赞
2019年10月9日 上午11:51 7楼
妙啊
2019年9月18日 下午2:21 8楼
期待了好久的三剑客之sed有得出来吗,不要忘记他的兄弟呀啊啊啊啊啊啊啊啊啊啊啊啊啊
2019年8月30日 下午9:01 9楼
花了几个小时把awk都看了一遍,感受颇深,看的晚饭都忘记吃,看完感觉好饱~好后悔这么晚才发现竟然有写的如此好的文章,希望朱老师多多分享干货
2019年8月31日 下午9:08 1层
@老年程序猿 捧场了,加油,共勉~~
2019年8月19日 下午3:46 10楼
膜拜,膜拜,膜拜。一扣首,再扣首,三扣首,礼毕
2019年8月15日 下午2:36 11楼
说好的Sed呢…三剑客缺了一个就不完美了呀哈啊啊啊啊啊啊啊
2019年8月12日 下午5:06 12楼
写的很好啊,谢谢博主
2019年7月29日 下午4:53 13楼
获益匪浅,希望还有下篇~
2019年7月3日 上午2:14 14楼
一口气读完了!写得太优秀了,很多系列文章让人看了几篇就放弃了,唯有这个带到最后!
2019年7月2日 下午4:14 15楼
花了两天时间读完了这11篇关于awk的博文,收获颇深,我之前有一定的awk基础,但是读了博主第一篇文章就深深的感觉相见很晚啊,之前不懂的地方,现在都有了深入的理解,主要是体系化了,
感谢博主
2019年6月30日 下午5:46 16楼
临别前村里的长者告诉我:去了大城市遇到知识渊博的人都要尊称”老师”,这个称号能让他们shuang
刚看完IPtables和awk的我有话要说:朱老师,你爽到我了,我想榨干你的精华,感谢朱老师的万千精华让我成长,正在入运维的门,希望在朱老师的指导下能过上左搂右抱的生活,也希望朱老师的博客越做越好,精华越产越多,福泽天下,雨露均沾,造福全人类……我的功力还是差老师太多太多,还得再接再励,努力学习,勇争第一,争做新时代”四有优秀青年”,争取早日扛起大旗,纵马驰骋,大杀四方,耀武扬威,扬名立外,足迹遍布天下,旌旗×满全图。
到时候,我就可以骄傲的告诉大家,拜师就得朱老师,走遍天下都不怕!
2019年6月30日 下午7:14 1层
@Ning 你爽到我了,优秀~加油~
2019年5月15日 下午4:43 17楼
赞,看完了,写的很好
2019年4月25日 上午11:32 18楼
感谢博猪,作者写的真认真,学到不少东西,再次感谢作者!
2019年4月8日 上午12:54 19楼
打卡,刷完,作者666
2019年4月3日 上午11:34 20楼
打印奇偶行完全可以使用自然一点的思路来实现。 打印偶数行:awk ‘NR%2==0’ file,打印奇数行:awk ‘NR%2!=0’ file
2019年9月24日 下午4:10 1层
@怒风 这只是告诉我们一个思路 ,新颖的语法
2019年3月30日 下午4:52 21楼
很好,点个赞
2019年3月17日 上午12:52 22楼
写的很棒!
2019年3月17日 上午12:51 23楼
awk ‘0’ file 假
awk ‘a’ file 假
awk ‘”a”‘ file 真
awk ‘a=”a”‘ file 真
awk ‘a=””‘ file 假
2019年3月1日 下午4:14 24楼
期待更新中。。。。
2019年1月21日 下午4:25 25楼
博主您还会更新吗?看的好爽,不过瘾呀
2018年12月20日 下午4:29 26楼
坐等博主继续更新,文章写得真棒
2018年11月23日 下午1:26 27楼
11篇就没了,期待继续更新啊
2018年11月12日 下午3:46 28楼
写的好, 挺用心的
2018年10月8日 下午7:30 29楼
i!=i 好骚
2018年11月14日 上午8:16 1层
@t i!=1没结果吧
应该是
i=!i
!(i=!i)
朱哥写到很详细,看了之后学到了不少东西
2019年2月18日 下午9:11 2层
@coool 写错了,呵呵哈哈哈哈哈哈哈哈
你也看错了,哈哈哈哈
2018年9月29日 下午2:12 30楼
一定常来
2018年9月19日 下午4:24 31楼
刷完了 虽然还有好多没记住的地方 需要多多练习 感谢作者 认认真真写了这么多的东西 而且用非常让人能够懂得的例子 用心了
2018年8月15日 下午6:45 32楼
刷完
2018年8月8日 下午5:32 33楼
这两天无意中看到朱兄的awk文章,一口气读完受益良多,感谢您的付出!
2018年6月20日 下午10:31 34楼
朱哥写的很认真,深入浅出,容易理解。收获满满,真心感谢!
2018年6月13日 上午12:39 35楼
同事发现这块好的地方,然后推荐给了我,《非常感谢推荐朱兄如此好地》然后被深深的吸引,目前撸完iptables与awk,继续撸,楼主写得非常好,看本篇awk是目前的最后一篇了,所以在此特意留言,每次看到@echo兄弟留言,甚想叠楼,但是时间过去良久,不便掘坟,在此再次感谢朱兄,准备将所有的都过一篇……感谢朱兄!
2018年6月12日 上午9:59 36楼
积少成多,感谢作者!
2018年3月27日 下午6:28 37楼
博主666
2018年1月22日 下午4:59 38楼
非常棒,赞一个,通俗易懂!
2017年8月22日 上午11:40 39楼
为什么一个赋值运算能在模式里做判断啊, ‘a = 1’ 可以理解为赋值运算返回值就是被赋的值吗
2017年8月22日 上午11:56 1层
@feyjobs 变量被赋值后,变量的值就是被赋予的值,而0为真,非0为假,并没有做所谓的判断,它直接就表示真或者假,
只不过你在使用模式时,模式需要进行判断,最终得出真假,而你对变量赋值时,就相当于直接赋值真假了,反而不用进行判断,直接指明真假了,
同时,你又省略了对应的动作,所以真的(与模式判断后为真的同理)默认会打印整行
2017年8月1日 下午3:17 40楼
博主能帮忙看下这是什么原因么?
[root@oldboy /]# su – test -c a.sh
-bash: a.sh: command not found
[root@oldboy /]# su – test -c /bin/sh a.sh
sh: cannot set terminal process group (-1): Inappropriate ioctl for device
sh: no job control in this shell
sh-4.1$
——————————————–分隔符———————————————–
a.sh内容 :echo 1234>>/a.txt 权限以及给了777 , sudo也配置了 test ALL=(ALL) NOPASSWD:ALL
2017年8月1日 下午5:02 1层
@易知难 su – test -c “/bin/sh a.sh”
评论中必须含有中文。。。。
2017年8月1日 下午6:19 2层
@妞妞 互助互爱,666,
2017年7月29日 上午10:36 41楼
打卡!小二 器大活好!!!5星好评!
2017年7月29日 上午11:43 1层
@易知难 这已经是最高评价了,嘿嘿,加油~~
2017年7月14日 下午6:20 42楼
2天awk系列看完,扩展正则那边,–posix 和–re-interval ubuntu系统无法使用,可能是ubuntu的awk不是gun awk,换到centos上正常,谢谢博主好文。
2017年7月15日 上午9:15 1层
@zero 客官学习速度没毛病,动手能力没毛病,能帮助到你也是我的初衷,加油~~
2017年7月19日 上午12:01 1层
@zero 厉害 能否加下我qq845893109
2017年7月19日 上午10:03 2层
@诸葛 实用运维QQ群:204721636
有兴趣的朋友可以添加,可以互相讨论
2019年4月25日 上午11:31 1层
@zero 我 Ubuntu 18.04 同参数 –posix 和 –re-interval 无法使用,估计也不是 gun awk