zoukankan      html  css  js  c++  java
  • awk (转)

    Awk是一种处理结构数据并输出格式化结果的编程语言, Awk 是其作者 "Aho,Weinberger,Kernighan" 的简称。

    Awk通常被用来进行格式扫描和处理。通过扫描一个或多个文件中的行,查看是否匹配指定的正则表达式,并执行相关的操作。

    Awk的主要特性包含:

    1. Awk以记录和字段的方式来查看文本文件

    2. 和其他编程语言一样,Awk 包含变量、条件和循环

    3. Awk能够进行运算和字符串操作

    4. Awk能够生成格式化的报表数据

    Awk从一个文件或者标准输入中读取数据,并输出结果到标准输出中。

    1.  Awk的语法

    1. Syntax:    
    2.     
    3. awk '/search pattern1/ {Actions}    
    4.      /search pattern2/ {Actions}' file    
     

    在上诉语法中:

    1. search pattern是正则表达式

    2. Actions 输出的语法

    3. Awk 中可以存在多个正则表达式和多个输出定义

    4. file 输入文件名

    5. 单引号的作用是包裹起来防止shell 截断

     

    2.  Awk的工作方式:

    1 Awk 一次读取文件中的一行

    2)对于一行,按照给定的正则表达式的顺序进行匹配,如果匹配则执行对应的 Action

    3)如果没有匹配上则不执行任何动作

    4)在上诉的语法中, Search Pattern  Action 是可选的,但是必须提供其中一个

    5)如果 Search Pattern 未提供,则对所有的输入行执行 Action 操作

    6)如果 Action 未提供,则默认打印出该行的数据

    7 {} 这种 Action 不做任何事情,和未提供的 Action 的工作方式不一样

    8 Action 中的语句应该使用分号分隔

    创建一个包含下面内容的文本文件employee.txt 。后续的例子中将会用到该文件

     

    1. $cat employee.txt    
    2. 100  Thomas  Manager    Sales       $5,000    
    3. 200  Jason   Developer  Technology  $5,500    
    4. 300  Sanjay  Sysadmin   Technology  $7,000    
    5. 400  Nisha   Manager    Marketing   $9,500    
    6. 500  Randy   DBA        Technology  $6,000    

     

    3.  Awk 的默认行为

    默认的时候awk 打印文件中的每一行

     

     

    1. $ awk '{print;}' employee.txt    
    2. 100  Thomas  Manager    Sales       $5,000    
    3. 200  Jason   Developer  Technology  $5,500    
    4. 300  Sanjay  Sysadmin   Technology  $7,000    
    5. 400  Nisha   Manager    Marketing   $9,500    
    6. 500  Randy   DBA      Technology  $6,000    

    在上面的例子中,匹配的正则表达式未给出,因此后续的Action 适用所有的行, Action 中的 print 没有任何参数的情况下将打印整行,注意其中的 Action 必须使用 {} 括起来。

    4.  Awk打印匹配的行

     

     

    1. $ awk '/Thomas/    
    2. > /Nisha/' employee.txt    
    3. 100  Thomas  Manager    Sales       $5,000    
    4. 400  Nisha   Manager    Marketing   $9,500    

    在上面的例子中,将打印包含Thomas  Nisha 的行,上面的列子包含两个正则表达式。 Awk 可以接受任意数量的正则表达式,但是每个组合 ( 正则表达式和对应的 Action) 必须用新行来分隔。

    5.  Awk仅打印指定的域

    Awk包含许多内建的变量,对于每行的记录, Awk 默认按照空格进行分割,并将分隔后的值存入对应的 $n 变量中。如果一行还有 4 个单词,将被分别存储进 $1 $2 $3 $4 中,其中 $0 代表整行。 NF 也是一个内建的变量,代表该行中分割后的变量数。

    1. $ awk '{print $2,$5;}' employee.txt    
    2. Thomas $5,000    
    3. Jason $5,500    
    4. Sanjay $7,000    
    5. Nisha $9,500    
    6. Randy $6,000    
    7. $ awk '{print $2,$NF;}' employee.txt    
    8. Thomas $5,000    
    9. Jason $5,500    
    10. Sanjay $7,000    
    11. Nisha $9,500    
    12. Randy $6,000   
     

    在上诉例子中$2  $5 分别代表名字和薪水,也可以使用 $NF 获得薪水,其中 $NF 代表最后一个字段,在打印语句中逗号是一个连接符号。

    6.  Awk开始和最后的动作

    Awk包含两个重要的关键字 BEGIN  END

     

     

    1. Syntax:     
    2.     
    3. BEGIN { Actions}    
    4. {ACTION} # Action for everyline in a file    
    5. END { Actions }    
    6. # Awk中的注释    

    BEGIN 节中的 Actions 会在读取文件中的行之前被执行。

    END 节中的 Actions 会在读取并处理文件中的所有行后被执行。

     

     

    1. $ awk 'BEGIN {print "Name/tDesignation/tDepartment/tSalary";}    
    2. > {print $2,"/t",$3,"/t",$4,"/t",$NF;}    
    3. > END{print "Report Generated/n--------------";    
    4. > }' employee.txt    
    5. Name Designation Department Salary    
    6. Thomas   Manager   Sales           $5,000    
    7. Jason   Developer   Technology   $5,500    
    8. Sanjay   Sysadmin   Technology   $7,000    
    9. Nisha   Manager   Marketing   $9,500    
    10. Randy   DBA     Technology   $6,000    
    11. Report Generated    
    12. --------------    

    上述的例子为输出结果增加头和尾描述

    7.  Awk找出员工 ID 大于 200 的员工

     

     

    1. $ awk '$1 >200' employee.txt    
    2. 300  Sanjay  Sysadmin   Technology  $7,000    
    3. 400  Nisha   Manager    Marketing   $9,500    
    4. 500  Randy   DBA        Technology  $6,000    

    在上述例子中,$1 代表员工 ID ,如果员工 ID 大于 200 则执行默认的打印整行的 Action 

    8.  Awk打印技术部员工

    $4代表员工所在的部门,如果等于 Technology 则打印出整行

     

     

    1. $ awk '$4 ~/Technology/' employee.txt    
    2. 200  Jason   Developer  Technology  $5,500    
    3. 300  Sanjay  Sysadmin   Technology  $7,000    
    4. 500  Randy   DBA      Technology  $6,000    

    ~操作符是和正则表达式中的值进行比较,如果匹配则打印整行

    9.  Awk打印技术部门的员工数

    在下面的例子中,检查员工的部门是否是Technology ,如果是则递增 count 变量的值。 Count 变量的值在BEGIN  Actions 中被初始化为 0 

     

     

    1. $ awk 'BEGIN { count=0;}    
    2. $4 ~ /Technology/ { count++; }    
    3. END { print "Number of employees in Technology Dept =",count;}' employee.txt    
    4. Number of employees in Tehcnology Dept = 3    

    在处理的最后(END  Actions) ,仅仅打印出 Technology 部门的人数



    在Linux awk语言中,提供了很多有意义的函数。例如:

           gsub(r,s)  在整个$0中用s代替r

           gsub(r,s,t) 在整个t上用s代替r

           length(s)   返回s的长度

           index(s,t)   返回s中字符串t的第一位置

           match(s,r)   测试s是否包含r 子串

           spilt(s,a,fs)  用fs(某种分割符号)去拆分s串,将拆分后的数组赋给a

           sub(r,s)        用$0中最左边最长的子串去代替s

           substr(s,p)   返回字符串s从p开始的后缀部分

           substr(s,p,n)   返回字符串s从p开始的长度为n的串

           现在分别举例子来看这些具体的应用:

          1:gsub

          下面一个例子将匹配chenwu串的行替换成yangliu(注意这里要加引号,不然awk会把它当作变量)

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ cat -n grade.txt   
    2.      1  chenwu 05/99 4811 27   
    3.      2  mary   02/22 1231 30  
    4.      3  tom    09/15 1182 25  
    5. [chenwu@localhost unit9-awkIntroduce]$ awk 'gsub(/chenwu/,"yangliu") {print $0}' grade.txt   
    6. yangliu 05/99 4811 27   

         2:index(获取ny串在Bonny的起始位置,注意这里的计数与一般的编程语言不同,这里从1开始计数)

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ awk 'BEGIN {print  index("Bonny","ny")}' grade.txt   
    2. 4  

     

         3:length

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ awk '{if($1=="chenwu") print $1,length($1)}' grade.txt  
    2. chenwu 6  

       4:match

           match用来匹配子串(也可以是一个正则表达式 )在父串的位置,如果匹配成功,则返回匹配的位置,否则返回0,例如:

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ awk 'BEGIN {print match("ABCD",/C/)}'  
    2. 3  
    3. [chenwu@localhost unit9-awkIntroduce]$ awk 'BEGIN {print match("ABCD",/U/)}'  
    4. 0  

     

       5:split

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ awk 'BEGIN {print split("123#45#22",myarray,"#")}'  
    2. 3  

     

       6:substr(s,p[,n])   返回s串中从p开始的后缀部分,n是一个可选参数,表示取多大的长度   

          例如

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ awk 'BEGIN {base="I love money"} {print substr(base,3,6)}' grade.txt   
    2. love m  
    3. love m  
    4. love m  

       awk的这些函数在和shell的管道符结合在一起的时候,可以发挥很大的作用。例如:

        返回一个目录下所有文件的句点的前缀名称。(不好使)

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ ls -l | awk 'BEGIN {if($1!~/^d/) n=index($8,".")}   
    2. {if($1!~/^d/) print n,substr($8,n)}'  
    3. 0   
    4. 0 grade.report  
    5. 0 grade.txt  
    6. [chenwu@localhost unit9-awkIntroduce]$ ls -l  
    7. 总计 12  
    8. -rw-rw-r-- 1 chenwu chenwu   53 06-10 10:16 grade.report  
    9. -rw-rw-r-- 1 chenwu chenwu   64 06-11 10:12 grade.txt  
    10. drwxrwxr-x 2 chenwu chenwu 4096 06-11 10:28 testDir  

     

        这里为什么不好使尼?理由是n在begin里定义了后,之后就不会再变了,稍微改造后,就好使了:

    Java代码  收藏代码
    1. [chenwu@localhost unit9-awkIntroduce]$ ls -l | awk '{n=index($8,".")} {if($1!~/^d/) print substr($8,1,n-1)}'  
    2.   
    3. grade  
    4. grade  

     

        但是这里还是有点瑕疵,你会发现并没有过滤普通目录。grade的上方仍然有输出(空白)

       一种较合理的解释是普通目录的确过滤掉了,但是ls -l最上方的总计12  没有过滤到,导致也对它取了次从1到句点.结束的子串,从而打印了空白。


    一个不会敲代码的程序员
  • 相关阅读:
    (数据科学学习手札09)系统聚类算法Python与R的比较
    写完代码就去吃饺子|The 10th Henan Polytechnic University Programming Contest
    《四月物语》
    PAT(甲级)2017年春季考试
    PAT(甲级)2017年秋季考试
    2019年全国高校计算机能力挑战赛 C语言程序设计决赛
    CF#603 Div2
    redhat7 上安装dummynet
    cassandra 如何写数据以及放置副本
    Eclipse中设置VM参数
  • 原文地址:https://www.cnblogs.com/hitwtx/p/2272121.html
Copyright © 2011-2022 走看看