zoukankan      html  css  js  c++  java
  • awk基本使用方法简单介绍

           之前说过sed, 今天来说awk, 它也是一个文本处理器。 是linux下的一个命令, 比sed更强大。 搞linux开发, 尤其是后台开发, 这个命令差点儿必需要用到。 awk这三个字母分别代表其三位作者的名字, 而不是某个/某些有意义单词的缩写。

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

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


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

    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
    
           之前。 我们用sed来输出行, 如今, 我们来感受一下用awk输出列, 例如以下:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $2}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

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


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

           以下, 我们依据awk的原型来一一说明:

            

            A.awk 

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


            B. option

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $2}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
            能够看到。 命令中没有选项, 也就是採用了默认选项, 如今如果a.txt中的文件内容为:

    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
           我们再用awk '{print $2}' a.txt就不灵了。 为什么呢? 由于awk '{print $2}' a.txt的选项为空, 默认的是以空格为分隔符, 显然不能进行划分。

    那怎么办呢? 此时, 我们应该显式地指明分隔符。 例如以下:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk -F "|" '{print $2}' a.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           这就对了。好了, 兴许我们仍然针对test.txt, 不针对a.txt. 也就是说。 採用默认的选项。


           C. pattern

           这个最好理解了。 比方, 条件就是一种模式(但模式不不过条件, 有可能是一些正則表達式等)。我们看到。 在awk '{print $2}' test.txt中。 是无条件的, 所谓无条件即为真。

    日本无条件投降。 大概就是这个意思。 当然。 为了讲清楚条件, 我们还是来看看:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '1<2 {print $2}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '1<1 {print $2}' test.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           我们看到。 当条件为真的时候, 才会有真正的打印, 反之, 打个屁。

    假设要打印整个文件。 能够这么搞:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '1' test.txt
    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
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '0' test.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

          能够看看到, 条件为真, 有打印。

    否则, 没有打印。



           D. action

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $2}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           当然, 假设你喜欢C/C++语言格式。 那全然能够写成:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{printf("%s
    ", $2)}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

           实际上。 在pattern部分, 我们是能够用C/C++语言的if等keyword的, 如:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{if(1<2) printf("%s
    ", $2)}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{if(1<1) printf("%s
    ", $2)}' test.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $


          我们看到, awk看似非常小, 事实上五脏俱全。

    弄清了上面的基本构成, awk就算基本入门了。 既然已经与awk有了初步的恋爱感觉了, 那就要趁热打铁的练习一下。

          

          一. awk的内置变量

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $0}' test.txt
    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
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $2}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
          再如:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $1, $3}' test.txt
    xxx English
    Monkey 90
    Cat 100
    Dog 60
    Tiger 85
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

          2. FILENAME表示文件名。 比方:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{printf("%s
    ", FILENAME)}' test.txt
    test.txt
    test.txt
    test.txt
    test.txt
    test.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           能够看到, 文件名称被打印出来了。 为什么是5个呢? 由于awk是逐行处理的。


           3. NR是当前的行数, 能够理解为number of row, 当然, 假设你非要说now row这种中式英语。 那也能够。

    总之。 你要明确。 NR非常实用。例如以下:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{printf("%d:%s
    ", NR, FILENAME)}' test.txt
    1:test.txt
    2:test.txt
    3:test.txt
    4:test.txt
    5:test.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           那要创建test1.txt---test5.txt怎么搞呢? 也非常easy, 联合我们之前介绍过的xargs, 例如以下:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{printf("%s%d
    ", FILENAME, NR)}' test.txt | xargs touch
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ ls
    test.txt  test.txt1  test.txt2  test.txt3  test.txt4  test.txt5
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
        

          4. FNR是文件里的行数。 和NR还是有点小小差别的。 且看:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ cp test.txt test_bak.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{printf("%d:%d:%s
    ", NR, FNR, FILENAME)}' test.txt test_bak.txt
    1:1:test.txt
    2:2:test.txt
    3:3:test.txt
    4:4:test.txt
    5:5:test.txt
    6:1:test_bak.txt
    7:2:test_bak.txt
    8:3:test_bak.txt
    9:4:test_bak.txt
    10:5:test_bak.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
         

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ echo "good good study" | awk '{print NF}'
    3
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
          可见有3个段, 以下我们看看test.txt的每行是不是有5个段:
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print NF}' test.txt
    5
    5
    5
    5
    5
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
          果然如此。

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk -F "|" '{print FS}' test.txt
    |
    |
    |
    |
    |
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
          

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


          二. 常见的一些pattern

           1. 条件式的pattern, 我们事实上已经熟悉了。 比方:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '1' test.txt
    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
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '1<=1' test.txt
    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
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '1<=0' test.txt
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk 'length > 30' test.txt
    xxx     Math English C++  Experiment
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    Tiger   95    85     90   Fantastic
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

            3. 继续条件pattern, 例如以下:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '$1=="Cat"' test.txt
    Cat     80    100    60   Perfect
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
            继续加个条件:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '$1!="Cat" && $3>=85' test.txt
    xxx     Math English C++  Experiment
    Monkey  100   90     95   Good
    Tiger   95    85     90   Fantastic
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
          

           4. 打印第2-4行:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk 'NR>=2 && NR<=4 {print $0}' test.txt
    Monkey  100   90     95   Good
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           别忘了, 我们的sed也能够, 也蛮牛逼的:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ sed -n "2,4"p test.txt
    Monkey  100   90     95   Good
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           好了, 条件式的pattern我们介绍到这里。 以下我们介绍与正則表達式有关的一些pattern.


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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '/Cat/' test.txt
    Cat     80    100    60   Perfect
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           对了,sed也有类似功能, 例如以下:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ sed -n "/Cat/"p test.txt
    Cat     80    100    60   Perfect
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

        

          6. 那能不能实现grep -v的功能呢? 肯定能够, 假设你觉得不能, 那太小看awk了, 且看:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '!/Cat/' test.txt
    xxx     Math English C++  Experiment
    Monkey  100   90     95   Good
    Dog     90    60     70   Great
    Tiger   95    85     90   Fantastic
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

          7. 输出以xxxxxx开头的行:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '/^C/' test.txt
    Cat     80    100    60   Perfect
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '/^(C|D)/' test.txt
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
      
          8. 输出以xxxxxx结尾的行:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '/t$/' test.txt
    xxx     Math English C++  Experiment
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '/100/ && $4 >= 60' test.txt
    Monkey  100   90     95   Good
    Cat     80    100    60   Perfect
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '/100/ && $4 > 60' test.txt
    Monkey  100   90     95   Good
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

          10. 最后再来一个:

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


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

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print $2}' test.txt
    Math
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{printf("%d
    ", $2)}' test.txt
    0
    100
    80
    90
    95
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

           2.  在action中也能够有种逻辑。 比方打印第2-4行:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{if(NR>=2 && NR<=4) print $0}' test.txt
    Monkey  100   90     95   Good
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $
           当然, 你也能够把这个if条件移动到pattern中去, 如:

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk 'NR>=2 && NR<=4 {print $0}' test.txt
    Monkey  100   90     95   Good
    Cat     80    100    60   Perfect
    Dog     90    60     70   Great
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

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

    Administrator@51B6904C3C8A485 ~/learn_awk
    $ awk '{print length}' test.txt
    36
    30
    33
    31
    35
    
    Administrator@51B6904C3C8A485 ~/learn_awk
    $

           实际上, awk还有非常多内建的函数。 本文无法覆盖awk的全部内容。 只提供冰山一角的一些东东, 但供入门肯定是没有问题的。兴许会更依据实际, 对本文进行逐渐补充和完好。 

           肚子饿了。 该吃饭了。








  • 相关阅读:
    Python自动化测试框架有哪些?
    Python正则表达式
    用户事务处理中同步请求与异步请求区别
    Python——数据结构—链表
    Mysql的隔离级别 以及对脏读、不可重复读、幻读的理解
    http协议及与https协议的区别
    Cookie与Session的区别
    Python——数据结构—数组
    Python—Flask写项目Mysql显示sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1038, 'Out of sort memory, consider increasing server sort buffer size')
    Python—将PyCharm中的代码提交在Gitee码云的方法
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5250089.html
Copyright © 2011-2022 走看看