zoukankan      html  css  js  c++  java
  • 【Linux】awk详细介绍

    awk简介

        awk是一种使用方便且表现力很强的编程语言,它可以应用在多种不同的计算与数据处理任务中。由于awk天生提供对文件中文本分列进行处理,所以如果一个文件中的每行都被特定的分隔符(常见的是空格)隔开,我们可以将这个文件看成是由很多列的文本组成,这样的文件最适合用awk进行处理,其实awk在工作中很多时候被用来处理log文件,进行一些统计工作等。

    环境描述

    文件file1.txt,存储了个人工作信息,这个文件包含名字,工作时间,每小时工资等信息

    Jack 10 12

    Alice 8 13

    Mary 9 20

    Susie 11 10


    awk程序的结构

    awk都是由一个或者多个模式-动作语句组成的序列:

    pattern { action }

    pattern { action }

    1.awk的基本操作是由输入行组成的序列中,陆续的扫描执行每一行,搜索可以被模式匹配的行,每一个输入行轮流被测试一遍,每匹配到一个模式,对应的动作就会执行,然后下一行开始,匹配重新开始,这个过程一直持续到文件被读取完毕为止。通常,模式是可选的,所以动作使用{}括起来,以便区分两者。

    2.命令行中的程序被单引号包围时,这个规定可以防止程序中的字符串(例如$)被shell解释,也可以让程序的的长度多于一行。

    3.当程序的长度比较短的时候,直接写会比较方便,但是比较长的时候,需要放到文件中,例如文件名为pgfile,这是只要键入

    awk –f pgfile

    4.模式

    模式中可以使用比较符>,>=,==,<,<=,!=,并且还可以使用并且与或者(&&,||)

    大于(>=):awk '$2>=10 { print $1 }' file1.txt

    大于(>):awk '$2>10 { print $1 }' file1.txt

    等于(==):awk '$2==10 { print $1 }' file1.txt

    不等于(!=):awk '$2!=10 { print $1 }' file1.txt

    小于等于(<=):awk '$2<=10 { print $1 }' file1.txt

    小于(<):awk '$2<10 { print $1 }' file1.txt

    并且&&:awk '$2=1 && $3<10 { print $1 }' file1.txt (打印的行满足$2>1并且$3<10)

    或者||:awk '$2>11 || $3<=10 { print $1 }' file1.txt (打印的行满足:当$2>11或者$3<=10的时候)


    特殊说明

    1.awk中的$1表示第一个字段,$2表示第二个字段,以此类推,$0表示一整行

    2.awk计算当前输入行的字段数量,并记录到一个内置变量NF中,因此程序{print NF}为打印输入行字段数量

    3.awk还提供了另外一个变量NR,我们可以使用NR和$0为每一行加上行号{ print $0,NR }

    4.单词也可以用于与表达式组合;例如:awk '{ print "Total pay for",$1,"is",$2*$3 }' file1.txt

    其它内置函数:

    awk定义了很多内置函数,下面我们根据函数类型列出常用的函数,下面的函数只是一部分,完整的函数列表则需要查阅awk的官方文档。

    算术:
    atan2(y,x) 返回 y/x 的反正切。
    cos(x) 返回 x 的余弦;x 是弧度。
    sin(x) 返回 x 的正弦;x 是弧度。
    exp(x) 返回 x 幂函数。
    log(x) 返回 x 的自然对数。
    sqrt(x) 返回 x 平方根。
    int(x) 返回 x 的截断至整数的值。
    rand() 返回任意数字 n,其中 0 <= n < 1。
    srand([expr]) 将 rand 函数的种子值设置为 Expr 参数的值,或如果省略 Expr 参数则使用某天的时间。返回先前的种子值。
    字符串:
    gsub(reg,str1,str2) 使用str1替换所有str2中符合正则表达式reg的子串
    sub(reg,str1,str2) 含义与gsub相同,只不过gsub是替换所有匹配,sub只替换第一个匹配
    index(str,substr) 返回substr在str中第一次出现的索引,注意索引从1开始计算,如果没有则返回0
    length(str) 返回str字符串的长度,length函数还可以返回数组元素的个数
    blength(str) 返回字符串的字节数
    match(str,reg) 与index函数一样,只不过reg使用正则表达式,例如match("hello",/lo/)
    split(str,array,reg)将str分隔成数组保存到array中,分隔使用正则reg,或者字符串都可以,返回数组长度
    tolower(str) 转换为小写
    toupper(str) 转换为大写
    substr(str,start,length) 截取字符串,从start索引开始的length个字符,如不指定length则截取到末尾,索引从1开始
    其他:
    system(command) 执行系统命令,返回退出码
    mktime( YYYY MM dd HH MM ss[ DST]) 生成时间格式
    strftime(format,timestamp) 格式化时间输出,将时间戳转换为时间字符串
    systime() 得到时间戳,返回从1970年1月1日开始到当前时间(不计闰年)的整秒数

    printf输出

    print用于简单快速输出,如果想要格式化输出,可以使用printf

    格式

    printf(format,value1,value2…valueN)

    format是一个字符串,包含按字面打印的文本,中间散布着格式说明,格式说明符用于说明如何打印。一个格式说明符是一个%,后面跟着几个字符,这些字符控制着一个value的输出格式。格式说明符的数量应该和打印的value一样多

    例如:

    awk '{ printf("Total pay for s% is %.2f ",$1,$2*$3) }' file1.txt

    但是printf不会自动产生换行符或空格符,用户必须自己创建。

    数据验证

    awk还是一款数据验证工具

    真是的数据总数存在错误的,检查数据是否有合理的值,格式是否正确,这种任务叫做数据验证。

    例如:

    awk 'NF != 3 { print $0,"Number of fields is not equal to 3" }' file1.txt

    BEGIN与END

    特殊的模式BEGIN在第一个输入文件的第一行之前被匹配,END在最后一个输入文件的最后一行被处理之后匹配

    Linux:/usr/local/sbin # echo -e '11 12 13 21 22 23' | awk 'BEGIN{ print "col1 col2 col3";print ""}{ print $2,$1,$3 }'
    col1 col2 col3

    12 11 13
    22 21 23

    此命令将echo输出的内容通过管道传输给awk,然后格式化输出,print ""为打印单独的空行。这里echo命令使用了-e选项的目的就是为了保持字符串中的 的格式能够生效,否则该换行将被忽略。

    Linux:/usr/local/sbin # echo -e "1 2 3" | awk 'BEGIN{ print "begin" }{ print $1 }END{ print "end" }'
    begin
    1
    end

    awk计算

    1.这个程序用于计算工作时间大于等于10h的员工数

    Linux:/usr/local/sbin # awk '$2>=10 { cnt=cnt+1 }END{ print cnt,"employees worked more than 10h"}' file1.txt
    2 employees worked more than 10h

    此处的cnt为自定义的变量,cnt=cnt+1的意思为:每次读取一行,如果满足则依次加1.

    2.计算员工的总报酬与平均报酬

    Linux:/usr/local/sbin # awk '{ pay=pay+$2*$3 }END{ print "Total pay is ",pay ;print "Average pay is ",pay/NR }' file1.txt
    Total pay is  514
    Average pay is  128.5

    当NR值为0的时候,则程序会报错提示除数不为0

    3.求出工作时间最长的

    Linux:/usr/local/sbin # awk '$2>maxtime {maxtime=$2;maxname=$1}END{ print maxtime,maxname }' file1.txt
    11 Susie

    变量maxtime保存的是数值,maxname保存的是字符串;

    4.拼接字符串

    Linux:/usr/local/sbin # awk '{ names=names $1 "@|@"}END{ print names}' file1.txt
    Jack@|@Alice@|@Mary@|@Susie@|@

    此命令是将员工名字以@|@的方式进行拼接,names为初始自定义变量。

    流程控制语句

    if-else语句

    Linux:/usr/local/sbin # echo -e '23 man Jack' | awk '{if($1<18) print "The boy is underage"; else print "The boy has group up"; }'
    The boy has group up

    根据孩子的年龄来判断该孩子是否成年,成年则打印The boy has group up否则打印 The boy is underage(该孩子未成年)

    while语句

    while含有条件判断和循环体,如果条件为真的话,循环体执行。

    Linux:/usr/local/sbin # awk 'BEGIN{ count=1;while(count<=6){ print count;count ++}}'
    1
    2
    3
    4
    5
    6

    count初始赋值为1,依次加1,当count超过6,则停止循环;

    for语句

    Linux:/usr/local/sbin # awk 'BEGIN{ for(i=1;i<=5;i++) print i }'
    1
    2
    3
    4
    5

    常用命令行

    awk 'END{print NR}' file1.txt  #输入总行数

    awk 'NR==2' file1.txt            #打印第二行

    awk '{print $NF}' file1.txt    #打印最后一列

    awk 'NF>2' file1.txt           #打印字段数多于2个的行

    awk '$NF>12' file1.txt         #打印字段数多于2个的行

    awk '{nf=nf+NF}END{ print nf }' file1.txt  #打印输出的字段总个数

    awk '/Su/{ line=line+1 }END{ print line}' file1.txt  #打印包含字符Su的行的数量

    awk '$2>maxnum {maxnum=$2;maxname=$1}END{ print maxnum,maxname}' file1.txt  #打印$2最大值

    awk 'NR>0' file1.txt  #打印至少包含一个字段的行

    awk 'length($0)>10' file1.txt  #打印长度超过10的行

    awk '{ print NF,$0 }' file1.txt #每一行前添加字段数

    awk '{ print $3,$2,$1 }' file1.txt #打印每一行的字段,但是顺序相反

    awk '{ $1=NR;print }' file1.txt #每一行的第一个字段用行号替换并打印

    awk '{ $2="";print }' file1.txt #打印除第二行外的其他行

    案例描述

    1.现在想求出每个人的当天的报酬信息(并且每个人的工作时间必须大于0)

    Linux:/usr/local/sbin # awk '$2>0 {print $1,$2*$3}' file1.txt

    Jack 120
    Alice 104
    Mary 180
    Susie 110

    该命令行告诉系统运行awk程序,被运行的程序用单引号包围起来,从file1.txt中获取数据,被单引号包围的是一个完整的awk程序,它由一个独立的模式-动作组成。模式$2 > 0扫描每一个输入行,如果该行的第二列大于0,则执行动作{print $1,$2*$3},此时就会为每一行匹配打印第一个字段,以及第二个字段与第三个字段的乘积,如果想知道工作时间为0的是谁,直接使用awk '$2==0 {print $1}' file1.txt即可打印出来。


    2.使用printf打印每位员工的名字与报酬

    Linux:/usr/local/sbin # awk '{ printf("%-8s $%6.2f ",$1,$2*$3) }' file1.txt
    Jack     $120.00
    Alice    $104.00
    Mary     $180.00
    Susie    $110.00

    第一个格式说明符%-8s,将名字左对齐输出,占用8个字符宽度;第二个格式说明符%6.2f,将报酬以美元并精确小数点2位,占用6个字符长度的方式打印出来。


    3.打印出报酬,并升序排序

    Linux:/usr/local/sbin # awk '{ printf("%6.2f %s ",$2*$3,$0)}' file1.txt | sort -n
    104.00 Alice 8 13
    110.00 Susie 11 10
    120.00 Jack 10 12
    180.00 Mary 9 20

    awk的输出通过管道传输给sort,排序后输出,-n是升序排序,如果需要降序排序,使用-r即可。


    4.打印文件的最后一行

    Linux:/usr/local/sbin # awk '{ last=$0 }END{ print last }' file1.txt
    Susie 11 10

























































  • 相关阅读:
    小甲鱼系列→第一章.基础知识
    FusionCharts-堆栈图、xml格式、刷新数据、添加事件link、传参
    FireBug提示:本页面不包含 JavaScript,明明是包含js的。
    Angular-Chart.js 初接触;;;
    错误 Metadata file 'C:CommoninDebugCommon.dll' could not be found
    UML--PowerDesigner使用小结
    java8入门 错误:找不到或者无法加载主类
    “基础提供程序在Open上失败”
    设计模式--目录开篇
    020医疗项目-模块二:药品目录的导入导出-介绍药品表
  • 原文地址:https://www.cnblogs.com/OliverQin/p/10164828.html
Copyright © 2011-2022 走看看