# awk从放弃到入门（11）：拾遗之”三元运算”与”打印奇偶行”

- 56

- A+

所属分类：Linux基础

> 在本博客中，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 对应的值。

当然，聪明如你，我就不用再解释打印偶数行的原理了，我想你应该已经能够举一反三了。

好了，这篇文章就写到这里，希望能够对你有所帮助~客官常来呦~~~

我的微信公众号
关注"实用运维笔记"微信公众号，当博客中有新文章时，可第一时间得知哦~
赞 68
赏
分享

- awk

- 版权声明：本站原创文章，于2017年7月9日00:35:19，由 朱双印 发表，共 2996 字。
- 如需转载，请在文章头部注明出处：awk从放弃到入门（11）：拾遗之”三元运算”与”打印奇偶行” | 朱双印博客

awk从放弃到入门（10）：awk内置函数
awk从放弃到入门（9）：awk数组详解
awk从放弃到入门（8）：awk动作总结之二
awk从放弃到入门（7）：awk动作总结之一

### 发表评论取消回复

欢迎 pangzi 再次光临！
修改信息

正在提交, 请稍候...
#

昵称*

邮箱*

网址

有回复时邮件通知我

## 目前评论：56 其中：访客 49 博主 7

2. 运维小白 2
   回复 2020年5月30日 下午4:48 沙发

   一天看完了博主的awk，受益匪浅，算是入门了吧。后续还要回来复习巩固

   - 弓长缔 0
     回复 2020年7月5日 上午2:51 1层

     @运维小白 一天？我都快看半年了还没掌握

4. blhj 1
   回复 2020年4月26日 下午8:37 板凳

   无语了,,,朱老师真棒.

6. gin 1
   回复 2020年1月7日 下午8:09 地板

   博主你的留言板怎么会把代码搞乱呢！而且还会自动丢掉一些数据！！！

8. gin 1
   回复 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

10. fisher 1
    回复 2019年12月20日 上午11:44 5楼

    都是九年义务教育,为何这么优秀,看完还想看一遍.

12. 无凉 0
    回复 2019年12月19日 下午9:01 6楼

    楼主讲得很清楚，赞

14. kaka 0
    回复 2019年10月9日 上午11:51 7楼

    妙啊

16. key 1
    回复 2019年9月18日 下午2:21 8楼

    期待了好久的三剑客之sed有得出来吗,不要忘记他的兄弟呀啊啊啊啊啊啊啊啊啊啊啊啊啊

18. 老年程序猿 0
    回复 2019年8月30日 下午9:01 9楼

    花了几个小时把awk都看了一遍，感受颇深，看的晚饭都忘记吃，看完感觉好饱~好后悔这么晚才发现竟然有写的如此好的文章，希望朱老师多多分享干货

    - 朱双印 Admin
      回复 2019年8月31日 下午9:08 1层

      @老年程序猿 捧场了，加油，共勉~~

20. 小脑斧与大灰囊 0
    回复 2019年8月19日 下午3:46 10楼

    膜拜，膜拜，膜拜。一扣首，再扣首，三扣首，礼毕

22. key 1
    回复 2019年8月15日 下午2:36 11楼

    说好的Sed呢…三剑客缺了一个就不完美了呀哈啊啊啊啊啊啊啊

24. lfy 1
    回复 2019年8月12日 下午5:06 12楼

    写的很好啊，谢谢博主

26. zhao 0
    回复 2019年7月29日 下午4:53 13楼

    获益匪浅，希望还有下篇~

28. skywind 1
    回复 2019年7月3日 上午2:14 14楼

    一口气读完了！写得太优秀了，很多系列文章让人看了几篇就放弃了，唯有这个带到最后！

30. codebin 0
    回复 2019年7月2日 下午4:14 15楼

    花了两天时间读完了这11篇关于awk的博文,收获颇深,我之前有一定的awk基础,但是读了博主第一篇文章就深深的感觉相见很晚啊,之前不懂的地方,现在都有了深入的理解,主要是体系化了,
    感谢博主

32. Ning 1
    回复 2019年6月30日 下午5:46 16楼

    临别前村里的长者告诉我：去了大城市遇到知识渊博的人都要尊称”老师”，这个称号能让他们shuang
    刚看完IPtables和awk的我有话要说：朱老师，你爽到我了，我想榨干你的精华，感谢朱老师的万千精华让我成长，正在入运维的门，希望在朱老师的指导下能过上左搂右抱的生活，也希望朱老师的博客越做越好，精华越产越多，福泽天下，雨露均沾，造福全人类……我的功力还是差老师太多太多，还得再接再励，努力学习，勇争第一，争做新时代”四有优秀青年”，争取早日扛起大旗，纵马驰骋，大杀四方，耀武扬威，扬名立外，足迹遍布天下，旌旗×满全图。
    到时候，我就可以骄傲的告诉大家，拜师就得朱老师，走遍天下都不怕！

    - 朱双印 Admin
      回复 2019年6月30日 下午7:14 1层

      @Ning 你爽到我了，优秀~加油~

34. 毅尝虚精 0
    回复 2019年5月15日 下午4:43 17楼

    赞，看完了，写的很好

36. 爱笑的张飞 1
    回复 2019年4月25日 上午11:32 18楼

    感谢博猪，作者写的真认真，学到不少东西，再次感谢作者！

38. zitherpeng 0
    回复 2019年4月8日 上午12:54 19楼

    打卡，刷完，作者666

40. 怒风 3
    回复 2019年4月3日 上午11:34 20楼

    打印奇偶行完全可以使用自然一点的思路来实现。 打印偶数行：awk ‘NR%2==0’ file，打印奇数行：awk ‘NR%2!=0’ file

    - chen 1
      回复 2019年9月24日 下午4:10 1层

      @怒风 这只是告诉我们一个思路 ，新颖的语法

42. Sky 0
    回复 2019年3月30日 下午4:52 21楼

    很好，点个赞

44. 蔷薇木人 1
    回复 2019年3月17日 上午12:52 22楼

    写的很棒！

46. abelzyp 1
    回复 2019年3月17日 上午12:51 23楼

    awk ‘0’ file 假
    awk ‘a’ file 假
    awk ‘”a”‘ file 真
    awk ‘a=”a”‘ file 真
    awk ‘a=””‘ file 假

48. 天尊 1
    回复 2019年3月1日 下午4:14 24楼

    期待更新中。。。。

50. 97号元素 0
    回复 2019年1月21日 下午4:25 25楼

    博主您还会更新吗？看的好爽，不过瘾呀

52. 涛子GE哥 0
    回复 2018年12月20日 下午4:29 26楼

    坐等博主继续更新，文章写得真棒

54. awker 2
    回复 2018年11月23日 下午1:26 27楼

    11篇就没了，期待继续更新啊

56. abcd 0
    回复 2018年11月12日 下午3:46 28楼

    写的好， 挺用心的

58. t 2
    回复 2018年10月8日 下午7:30 29楼

    i!=i 好骚

    - coool 1
      回复 2018年11月14日 上午8:16 1层

      @t i!=1没结果吧
      应该是
      i=!i
      !(i=!i)

      朱哥写到很详细，看了之后学到了不少东西

      - t 2
        回复 2019年2月18日 下午9:11 2层

        @coool 写错了，呵呵哈哈哈哈哈哈哈哈

        你也看错了，哈哈哈哈

60. 西门大官人 2
    回复 2018年9月29日 下午2:12 30楼

    一定常来

62. sunshineyifei 1
    回复 2018年9月19日 下午4:24 31楼

    刷完了 虽然还有好多没记住的地方 需要多多练习 感谢作者 认认真真写了这么多的东西 而且用非常让人能够懂得的例子 用心了

64. 鹿少 2
    回复 2018年8月15日 下午6:45 32楼

    刷完

66. changshao 0
    回复 2018年8月8日 下午5:32 33楼

    这两天无意中看到朱兄的awk文章，一口气读完受益良多，感谢您的付出！

68. xiaoshami 0
    回复 2018年6月20日 下午10:31 34楼

    朱哥写的很认真，深入浅出，容易理解。收获满满，真心感谢！

70. drgcaosheng 4
    回复 2018年6月13日 上午12:39 35楼

    同事发现这块好的地方，然后推荐给了我，《非常感谢推荐朱兄如此好地》然后被深深的吸引，目前撸完iptables与awk，继续撸，楼主写得非常好，看本篇awk是目前的最后一篇了，所以在此特意留言，每次看到@echo兄弟留言，甚想叠楼，但是时间过去良久，不便掘坟，在此再次感谢朱兄，准备将所有的都过一篇……感谢朱兄！

72. tom 1
    回复 2018年6月12日 上午9:59 36楼

    积少成多，感谢作者！

74. 星月 1
    回复 2018年3月27日 下午6:28 37楼

    博主666

76. kenny 2
    回复 2018年1月22日 下午4:59 38楼

    非常棒，赞一个，通俗易懂！

78. feyjobs 1
    回复 2017年8月22日 上午11:40 39楼

    为什么一个赋值运算能在模式里做判断啊, ‘a = 1’ 可以理解为赋值运算返回值就是被赋的值吗

    - 朱双印 Admin
      回复 2017年8月22日 上午11:56 1层

      @feyjobs 变量被赋值后，变量的值就是被赋予的值，而0为真，非0为假，并没有做所谓的判断，它直接就表示真或者假，
      只不过你在使用模式时，模式需要进行判断，最终得出真假，而你对变量赋值时，就相当于直接赋值真假了，反而不用进行判断，直接指明真假了，
      同时，你又省略了对应的动作，所以真的（与模式判断后为真的同理）默认会打印整行

80. 易知难 4
    回复 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

    - 妞妞 4
      回复 2017年8月1日 下午5:02 1层

      @易知难 su – test -c “/bin/sh a.sh”
      评论中必须含有中文。。。。

      - 朱双印 Admin
        回复 2017年8月1日 下午6:19 2层

        @妞妞 互助互爱，666，

82. 易知难 4
    回复 2017年7月29日 上午10:36 41楼

    打卡！小二 器大活好！！！5星好评！

    - 朱双印 Admin
      回复 2017年7月29日 上午11:43 1层

      @易知难 这已经是最高评价了，嘿嘿，加油~~

84. zero 1
    回复 2017年7月14日 下午6:20 42楼

    2天awk系列看完，扩展正则那边，–posix 和–re-interval ubuntu系统无法使用，可能是ubuntu的awk不是gun awk，换到centos上正常，谢谢博主好文。

    - 朱双印 Admin
      回复 2017年7月15日 上午9:15 1层

      @zero 客官学习速度没毛病，动手能力没毛病，能帮助到你也是我的初衷，加油~~

    - 诸葛 0
      回复 2017年7月19日 上午12:01 1层

      @zero 厉害 能否加下我qq845893109

      - 朱双印 Admin
        回复 2017年7月19日 上午10:03 2层

        @诸葛 实用运维QQ群：204721636
        有兴趣的朋友可以添加，可以互相讨论

    - 爱笑的张飞 1
      回复 2019年4月25日 上午11:31 1层

      @zero 我 Ubuntu 18.04 同参数 –posix 和 –re-interval 无法使用，估计也不是 gun awk

- 文章目录

×
×
拖拽到此处
图片将完成下载