Chinaunix首页 | 论坛 | 认证专区 | 博客 登录 | 注册
  • 博客访问: 5577
  • 博文数量: 17
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 17
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-17 22:52
  • 认证徽章:
文章分类
文章存档

2017年(17)

我的朋友
微信关注

IT168企业级官微



微信号:IT168qiye



系统架构师大会



微信号:SACC2013

分类: LINUX

原文地址:awk & sed之奇数行与偶数行的打印 作者:zooyo

  对于这个问题或许大家觉得不难,确实也不是什么太难的问题,首先想到的是对2的取余,诚然,在编程思想里这是一个概念。下面我们看看几个例子。
 
  1. $ cat file
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. $ awk 'NR%2' file
  9. 1
  10. 3
  11. 5
  12. $ awk '!(NR%2)' file
  13. 2
  14. 4
  15. 6

[解析]

  这应该是最标准的答案,NR是行号,awk的内建函数,当第一行,NR==1时,对2取余,结果是1,在awk的执行模式里,这个1就是pattern,为真,执行默认的{print},这个action操作。那么打印出该行,到第2行则余数是0,pattern为0,则为假,不会执行默认的{print},则不会输出偶数行。就达到了只输出奇数行的效果,反之则输出偶数行了。我们再看看一个更新颖的办法。

  1. $ awk '++i%2' file
  2. 1
  3. 3
  4. 5
  5. $ awk 'i++%2' file
  6. 2
  7. 4
  8. 6

[解析]

  这行命令充分的利用了C语言中 ++i 与 i++ 的区别,i++ 中i的值自加一次后这个表达式的结果等于1,但此时i的值仍然为0,为什么呢?i的值在当前表达式中不会改变,++i中i的值自加一次后,i的值是1,听起来很矛盾?确实比较饶口,我们再调用一个C程序来说明例子:

  1. # include <stdio.h>
  2. int main(void)
  3. {
  4.     int i, j, a, b;
  5.     i = j = 0;
  6.     a = i++;
  7.     b = ++j;
  8.     printf ("a = %d , i = %d , b = %d , j = %d\n",a,i,b,j);
  9.     return 0;
  10. }
  11. /*
  12. 运行结果:
  13. a = 0 , i = 1 , b = 1 , j = 1
  14. */

[解析]

  在这个C语言程序中不难看出,a的值是0,i的值却是1,i++ 是把自加前的值赋予了a,则 ++i 不一样。这就可以解释为什么 i++ 输出的是偶数行了,第一行时,因为对2取余的时候 i++ 自加一次后的值是1,但 i++ 是把i的自加前的值去对2取余的,0对2取余结果为0,条件为假,到第二行的时候i的值才是上次自加后的值为1,对2取余数为1,pattern为真,则输出第2行,以此类推。++i 则是自加后i的值是1,所以输出的奇数行。++i 和 i++ 他们自加的结果都是i为1,但是在赋值和比较的时候,却是有区别的。看到这里我想聪明的您已经明白了它们的区别。我们再看看第三中方法。

 

  1. $ awk 'i=!i' file
  2. 1
  3. 3
  4. 5
  5. $ awk '!(i=!i)' file
  6. 2
  7. 4
  8. 6

[解析]

  这句还需要我解释吗?阁下想必已经明白其中的奥妙了吧。^_^

 

  1. $ awk 'and(FNR,1)' file
  2. 1
  3. 3
  4. 5
  5. $ awk '!and(FNR,1)' file
  6. 2
  7. 4
  8. 6

[解析]

  awk里面有三个built-in function,分别是:and(a, b)按位与,or(a, b)按位或,xor(a, b)按位异或,当FNR为1的时候,就是第一行,1的2进制为0001,与0001按位与,得到结果是0001,0001的结果为真,就打印改行,当FNR为2时二进制表示为0010,那么又与0001相与,结果为0000,条件为假,则不打印。只有当FNR为奇数时,二进制的尾数为1,与0001相与结果才为真,否则结果都为假。即只输出奇数行,非则输出偶数行。

 

  1. $ sed -n 'p;n' file
  2. 1
  3. 3
  4. 5
  5. $ sed -n 'n;p' file
  6. 2
  7. 4
  8. 6

[解析]

  sed也不难解释,好好看看手册吧。

 

  1. $ seq 6 | sed -n '1~2p'
  2. 1
  3. 3
  4. 5
  5. $ seq 6 | sed -n '0~2p'
  6. 2
  7. 4
  8. 6

[解析]

  FIRST~STEP
  This GNU extension matches every STEPth line starting with line FIRST.In particular, lines will be selected when there exists a non-negative N such that the current line-number equals FIRST + (N * STEP).  Thus, to select the odd-numbered lines, one would use`1~2'.



  1. seq 10 | sed '0~3a\=='

  2. seq 10 | awk 'ORS=NR%3?"\n":"\n==\n"

[解析]

每隔三行就在后面添加一个分割符。

阅读(606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册