Linux文本操作三剑客(sed, awk, grep)——awk

来源:互联网 发布:啥录屏软件好 编辑:程序博客网 时间:2024/06/05 17:58

一句话总结:功能强大,擅长文本分析及处理,以行为单位,每行又可分为多个字段做处理。

1、awk [-F field-separator] 'commands' input-file(s)
commands 是真正awk命令,[-F域分隔符]是可选的。 input-file(s) 是待处理的文件。
在awk中,文件的每一行中,由域分隔符分开的每一项称为一个域。通常,在不指名-F域分隔符的情况下,默认的域分隔符是空格。

支持C/C++语言

zjy@ubuntu:~$ awk -F " " '1<2 {if(1<2) printf("%s\n", $2)}' ttt.c 

math

100

80

90

95


zjy@ubuntu:


2、为何打印文件名打印了6个,因为ttt.c有6行,awk是按行处理的

zjy@ubuntu:~$ awk '{printf("%s\n", FILENAME)}' ttt.c 

ttt.c

ttt.c

ttt.c

ttt.c

ttt.c

ttt.c

zjy@ubuntu:~$ cat ttt.c 

xxx math English C++  Experiment  

Monkey  100   90     95   Good  

Cat     80    100    60   Perfect  

Dog     90    60     70   Great  

Tiger   95    85     90   Fantastic  


zjy@ubuntu:~$


3、NR(number of row)表示行数,很有用;NF(number of filed)表示字段;FS(filed separator)字段分隔符;区别与文件行数FNR

zjy@ubuntu:~$ awk '{printf("%d:%s\n", NR, FILENAME)}' ttt.c 

1:ttt.c

2:ttt.c

3:ttt.c

4:ttt.c

5:ttt.c

6:ttt.c

zjy@ubuntu:~$ awk '{printf("%d:%d:%s\n", NR, FNR, FILENAME)}' ttt.c ttt.c 

1:1:ttt.c  文件ttt.c的第1行

2:2:ttt.c

3:3:ttt.c

4:4:ttt.c

5:5:ttt.c

6:6:ttt.c   文件的第6行

7:1:ttt.c   文件txt.c的第1行

8:2:ttt.c

9:3:ttt.c

10:4:ttt.c

11:5:ttt.c

12:6:ttt.c

zjy@ubuntu:~$ echo "hello|world|hi" | awk -F "|" '{print NF}'

3

zjy@ubuntu:~$ echo "hello world hi" | awk '{print NF}'

3

zjy@ubuntu:~$ echo "hello|world|hi

> oh|god|haha" | awk -F "|" '{print FS}'

|

|

zjy@ubuntu:~

4、字符串匹配查找

zjy@ubuntu:~$ cat ttt.c 

xxx math English C++  Experiment  

Monkey  100   90     95   Good  

Cat     80    100    60   Perfect  

Dog     90    60     70   Great  

Tiger   95    85     90   Fantastic  

Tiger

zjy@ubuntu:~$ awk '/^C/' ttt.c 

Cat     80    100    60   Perfect  

zjy@ubuntu:~$ awk '/^(C|T)/' ttt.c 

Cat     80    100    60   Perfect  

Tiger   95    85     90   Fantastic  

Tiger

zjy@ubuntu:~$ awk '/r$/' ttt.c 

Tiger

zjy@ubuntu:~$ awk '/Cat/' ttt.c 

Cat     80    100    60   Perfect  

zjy@ubuntu:~$ awk '!/Cat/' ttt.c 

xxx math English C++  Experiment  

Monkey  100   90     95   Good  

Dog     90    60     70   Great  

Tiger   95    85     90   Fantastic  

Tiger

zjy@ubuntu:~


下面文章不错,就不再截图写了,基本都差不多,转载于:http://blog.csdn.net/stpeace/article/details/46848873

awk也是一个文本处理器, 是linux下的一个命令, 比sed更强大。 搞linux开发, 尤其是后台开发, 这个命令几乎必须要用到。 awk这三个字母分别代表其三位作者的名字, 而不是某个/某些有意义单词的缩写。

       还是那句话,以实践操作为荣, 以只看不练为耻。当然, 理解awk的原理是必须的:读入有'\n'换行符分割的一条记录,将记录按指定的域分隔符划分域,$0表示所有域, $1表示第一个域, $n表示第n个域。 默认域分隔符是空格键或tab键。

       鉴于awk涉及的东西太多, 所以本文中, 我们仅仅介绍基本的用法, 以后遇到了新的东东, 再添加到本博文中, 滚雪球似地积累。


       先来感受一下awk, 我们假设test.txt中的内容:

[plain] view plain copy
  1. xxx     Math English C++  Experiment  
  2. Monkey  100   90     95   Good  
  3. Cat     80    100    60   Perfect  
  4. Dog     90    60     70   Great  
  5. Tiger   95    85     90   Fantastic  
       之前, 我们用sed来输出行, 现在, 我们来感受一下用awk输出列, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print $2}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  

       看到了吧, 这就是awk. 注意上面只能是单引号, 不能是双引号, $2表示第二列。


      
       我们来看看awk的一般格式:awk [option]  'pattern {action}' test.txt,  比如上面的awk '{print $2}' test.txt, 此时,采用默认选项, 且条件永远为真。

       下面, 我们根据awk的原型来一一说明:

        

        A.awk 

        其实awk就相当于一个函数名, 没什么好说的了。


        B. option

        我们先看如下操作, 打印test.txt文件的第二列:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print $2}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
        可以看到, 命令中没有选项, 也就是采用了默认选项, 现在假设a.txt中的文件内容为:

[plain] view plain copy
  1. xxx|Math|English|C++|Experiment  
  2. Monkey|100|90|95|Good  
  3. Cat|80|100|60|Perfect  
  4. Dog|90|60|70|Great  
  5. Tiger|95|85|90|Fantastic  
       我们再用awk '{print $2}' a.txt就不灵了, 为什么呢? 因为awk '{print $2}' a.txt的选项为空, 默认的是以空格为分隔符, 显然不能进行划分。 那怎么办呢? 此时, 我们应该显式地指明分隔符, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk -F "|" '{print $2}' a.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  
       这就对了。好了, 后续我们仍然针对test.txt, 不针对a.txt. 也就是说, 采用默认的选项。


       C. pattern

       这个最好理解了, 比如, 条件就是一种模式(但模式不仅仅是条件, 有可能是一些正则表达式等)。我们看到, 在awk '{print $2}' test.txt中, 是无条件的, 所谓无条件即为真。 日本无条件投降, 大概就是这个意思。 当然, 为了讲清楚条件, 我们还是来看看:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '1<2 {print $2}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $ awk '1<1 {print $2}' test.txt  
  11.   
  12. Administrator@51B6904C3C8A485 ~/learn_awk  
  13. $  
       我们看到, 当条件为真的时候, 才会有真正的打印, 反之, 打个屁。 如果要打印整个文件, 可以这么搞:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '1' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Monkey  100   90     95   Good  
  5. Cat     80    100    60   Perfect  
  6. Dog     90    60     70   Great  
  7. Tiger   95    85     90   Fantastic  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $ awk '0' test.txt  
  11.   
  12. Administrator@51B6904C3C8A485 ~/learn_awk  
  13. $  

      可以看看到, 条件为真, 有打印。 否则, 没有打印。

       D. action

       这个好理解, 无非就是内置命令而已, 比如print $2, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print $2}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  
       当然, 如果你喜欢C/C++语言格式, 那完全可以写成:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{printf("%s\n", $2)}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  

       实际上, 在pattern部分, 我们是可以用C/C++语言的if等关键字的, 如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{if(1<2) printf("%s\n", $2)}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $ awk '{if(1<1) printf("%s\n", $2)}' test.txt  
  11.   
  12. Administrator@51B6904C3C8A485 ~/learn_awk  
  13. $  


      我们看到, awk看似很小, 其实五脏俱全。 弄清了上面的基本构成, awk就算基本入门了。 既然已经与awk有了初步的恋爱感觉了, 那就要趁热打铁的练习一下。

      

      一. awk的内置变量

      1. $0表示整行, $n表示第n个分段, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print $0}' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Monkey  100   90     95   Good  
  5. Cat     80    100    60   Perfect  
  6. Dog     90    60     70   Great  
  7. Tiger   95    85     90   Fantastic  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $ awk '{print $2}' test.txt  
  11. Math  
  12. 100  
  13. 80  
  14. 90  
  15. 95  
  16.   
  17. Administrator@51B6904C3C8A485 ~/learn_awk  
  18. $  
      再如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print $1, $3}' test.txt  
  3. xxx English  
  4. Monkey 90  
  5. Cat 100  
  6. Dog 60  
  7. Tiger 85  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  

      2. FILENAME表示文件名称, 比如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{printf("%s\n", FILENAME)}' test.txt  
  3. test.txt  
  4. test.txt  
  5. test.txt  
  6. test.txt  
  7. test.txt  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  
       可以看到, 文件名被打印出来了, 为什么是5个呢? 因为awk是逐行处理的。


       3. NR是当前的行数, 可以理解为number of row, 当然, 如果你非要说now row这样的中式英语, 那也可以。总之, 你要明白, NR很有用。如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{printf("%d:%s\n", NR, FILENAME)}' test.txt  
  3. 1:test.txt  
  4. 2:test.txt  
  5. 3:test.txt  
  6. 4:test.txt  
  7. 5:test.txt  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  
       那要创建test1.txt---test5.txt怎么搞呢? 也很简单, 联合我们之前介绍过的xargs, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{printf("%s%d\n", FILENAME, NR)}' test.txt | xargs touch  
  3.   
  4. Administrator@51B6904C3C8A485 ~/learn_awk  
  5. $ ls  
  6. test.txt  test.txt1  test.txt2  test.txt3  test.txt4  test.txt5  
  7.   
  8. Administrator@51B6904C3C8A485 ~/learn_awk  
  9. $  
    

      4. FNR是文件中的行数, 和NR还是有点小小区别的, 且看:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ cp test.txt test_bak.txt  
  3.   
  4. Administrator@51B6904C3C8A485 ~/learn_awk  
  5. $ awk '{printf("%d:%d:%s\n", NR, FNR, FILENAME)}' test.txt test_bak.txt  
  6. 1:1:test.txt  
  7. 2:2:test.txt  
  8. 3:3:test.txt  
  9. 4:4:test.txt  
  10. 5:5:test.txt  
  11. 6:1:test_bak.txt  
  12. 7:2:test_bak.txt  
  13. 8:3:test_bak.txt  
  14. 9:4:test_bak.txt  
  15. 10:5:test_bak.txt  
  16.   
  17. Administrator@51B6904C3C8A485 ~/learn_awk  
  18. $  
     

     5. NF表示当前行有多少个段, 学这些东西的时候, 不要死记, 要知道NF是number of field的缩写, 那就清晰了, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ echo "good good study" | awk '{print NF}'  
  3. 3  
  4.   
  5. Administrator@51B6904C3C8A485 ~/learn_awk  
  6. $  
      可见有3个段, 下面我们看看test.txt的每行是不是有5个段:
[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print NF}' test.txt  
  3. 5  
  4. 5  
  5. 5  
  6. 5  
  7. 5  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  
      果然如此。

      6. FS是filed seperator, 也就是段分割符号, 默认情况下为空格, 下面我们不用默认的, 而用"|", 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk -F "|" '{print FS}' test.txt  
  3. |  
  4. |  
  5. |  
  6. |  
  7. |  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  
      

      当然, 还有其他的一些内置变量, 在此就不一一举例了, 以后要用的时候, 一查便知。


      二. 常见的一些pattern

       1. 条件式的pattern, 我们其实已经熟悉了, 比如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '1' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Monkey  100   90     95   Good  
  5. Cat     80    100    60   Perfect  
  6. Dog     90    60     70   Great  
  7. Tiger   95    85     90   Fantastic  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $ awk '1<=1' test.txt  
  11. xxx     Math English C++  Experiment  
  12. Monkey  100   90     95   Good  
  13. Cat     80    100    60   Perfect  
  14. Dog     90    60     70   Great  
  15. Tiger   95    85     90   Fantastic  
  16.   
  17. Administrator@51B6904C3C8A485 ~/learn_awk  
  18. $ awk '1<=0' test.txt  
  19.   
  20. Administrator@51B6904C3C8A485 ~/learn_awk  
  21. $  
       

       2. 来个复杂一点的条件pattern, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk 'length > 30' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Cat     80    100    60   Perfect  
  5. Dog     90    60     70   Great  
  6. Tiger   95    85     90   Fantastic  
  7.   
  8. Administrator@51B6904C3C8A485 ~/learn_awk  
  9. $  

        3. 继续条件pattern, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '$1=="Cat"' test.txt  
  3. Cat     80    100    60   Perfect  
  4.   
  5. Administrator@51B6904C3C8A485 ~/learn_awk  
  6. $  
        继续加个条件:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '$1!="Cat" && $3>=85' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Monkey  100   90     95   Good  
  5. Tiger   95    85     90   Fantastic  
  6.   
  7. Administrator@51B6904C3C8A485 ~/learn_awk  
  8. $  
      

       4. 打印第2-4行:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk 'NR>=2 && NR<=4 {print $0}' test.txt  
  3. Monkey  100   90     95   Good  
  4. Cat     80    100    60   Perfect  
  5. Dog     90    60     70   Great  
  6.   
  7. Administrator@51B6904C3C8A485 ~/learn_awk  
  8. $  
       别忘了, 我们的sed也可以, 也蛮牛逼的:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ sed -n "2,4"p test.txt  
  3. Monkey  100   90     95   Good  
  4. Cat     80    100    60   Perfect  
  5. Dog     90    60     70   Great  
  6.   
  7. Administrator@51B6904C3C8A485 ~/learn_awk  
  8. $  
       好了, 条件式的pattern我们介绍到这里, 下面我们介绍与正则表达式有关的一些pattern.


       5. 行过滤, 类似于grep的功能, 如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '/Cat/' test.txt  
  3. Cat     80    100    60   Perfect  
  4.   
  5. Administrator@51B6904C3C8A485 ~/learn_awk  
  6. $  
       对了,sed也有类似功能, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ sed -n "/Cat/"p test.txt  
  3. Cat     80    100    60   Perfect  
  4.   
  5. Administrator@51B6904C3C8A485 ~/learn_awk  
  6. $  

    

      6. 那能不能实现grep -v的功能呢? 肯定可以, 如果你认为不能, 那太小看awk了, 且看:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '!/Cat/' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Monkey  100   90     95   Good  
  5. Dog     90    60     70   Great  
  6. Tiger   95    85     90   Fantastic  
  7.   
  8. Administrator@51B6904C3C8A485 ~/learn_awk  
  9. $  

      7. 输出以xxxxxx开头的行:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '/^C/' test.txt  
  3. Cat     80    100    60   Perfect  
  4.   
  5. Administrator@51B6904C3C8A485 ~/learn_awk  
  6. $ awk '/^(C|D)/' test.txt  
  7. Cat     80    100    60   Perfect  
  8. Dog     90    60     70   Great  
  9.   
  10. Administrator@51B6904C3C8A485 ~/learn_awk  
  11. $  
  
      8. 输出以xxxxxx结尾的行:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '/t$/' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Cat     80    100    60   Perfect  
  5. Dog     90    60     70   Great  
  6.   
  7. Administrator@51B6904C3C8A485 ~/learn_awk  
  8. $  
       

      9. 自然而言地, 在一个pattern里, 我们可以既有正则又有条件, 如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '/100/ && $4 >= 60' test.txt  
  3. Monkey  100   90     95   Good  
  4. Cat     80    100    60   Perfect  
  5.   
  6. Administrator@51B6904C3C8A485 ~/learn_awk  
  7. $ awk '/100/ && $4 > 60' test.txt  
  8. Monkey  100   90     95   Good  
  9.   
  10. Administrator@51B6904C3C8A485 ~/learn_awk  
  11. $  

      10. 最后再来一个:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '/^x/, /^D/' test.txt  
  3. xxx     Math English C++  Experiment  
  4. Monkey  100   90     95   Good  
  5. Cat     80    100    60   Perfect  
  6. Dog     90    60     70   Great  
  7.   
  8. Administrator@51B6904C3C8A485 ~/learn_awk  
  9. $  
       当然了, sed肯定也有此功能, 不信你就翻翻我之前的博文。


       三. 常见的一些action, 实际上主要是内置函数

       1. 最常见的print, printf, 如下:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print $2}' test.txt  
  3. Math  
  4. 100  
  5. 80  
  6. 90  
  7. 95  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $ awk '{printf("%d\n", $2)}' test.txt  
  11. 0  
  12. 100  
  13. 80  
  14. 90  
  15. 95  
  16.   
  17. Administrator@51B6904C3C8A485 ~/learn_awk  
  18. $  

       2.  在action中也可以有种逻辑, 比如打印第2-4行:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{if(NR>=2 && NR<=4) print $0}' test.txt  
  3. Monkey  100   90     95   Good  
  4. Cat     80    100    60   Perfect  
  5. Dog     90    60     70   Great  
  6.   
  7. Administrator@51B6904C3C8A485 ~/learn_awk  
  8. $  
       当然, 你也可以把这个if条件移动到pattern中去, 如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk 'NR>=2 && NR<=4 {print $0}' test.txt  
  3. Monkey  100   90     95   Good  
  4. Cat     80    100    60   Perfect  
  5. Dog     90    60     70   Great  
  6.   
  7. Administrator@51B6904C3C8A485 ~/learn_awk  
  8. $  

      3.  计算字符串长度, 相当于C/C++中的length函数
[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ echo "good good study" | awk '{print length}'  
  3. 15  
  4.   
  5. Administrator@51B6904C3C8A485 ~/learn_awk  
  6. $  
       再如:

[plain] view plain copy
  1. Administrator@51B6904C3C8A485 ~/learn_awk  
  2. $ awk '{print length}' test.txt  
  3. 36  
  4. 30  
  5. 33  
  6. 31  
  7. 35  
  8.   
  9. Administrator@51B6904C3C8A485 ~/learn_awk  
  10. $  

       实际上, awk还有很多内建的函数。 本文无法覆盖awk的所有内容, 仅仅提供冰山一角的一些东东, 但供入门肯定是没有问题的。后续会更根据实际, 对本文进行逐渐补充和完善。 

       肚子饿了, 该吃饭了。