• 第10章:awk进阶操作


    10章:awk进阶操作

         在第4章:查找与替换简单的讲解了awk的使用,本章介绍详细讲解awk的使用。awk是一个强大的文本分析工具,简单的说awk就是把文件逐行的读入,

      以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。在shell脚本中文本处理功能awk功能其强大。

    7.1awk命令形式

             awk命令在shell脚本基本形式通常由四部分组成: [-F|-f|-v] (参数选项)、BEGIN语句块(初始化代码块)、pattern{commadns}(能够使用模式匹配的通用语句块)、END语句块(结束代码块),这四部分是可选择的,任意一部分都可以不出现在脚本中,后面三部分通常是被单引号或双引号括起来,awk命令形式如下所示:

    awk [-F|-f|-v]  ‘BEGIN{ commands }  /pattern/{ commands }  END{ commands}’  filename

     

    四部分分别代表意义:

    [-F|-f|-v]    参数选项:-F指定分隔符,-f调用脚本,-v定义变量 如var=value。

    BEGIN{ commands }  初始化代码块:在对第一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符。

    /pattern/{ commands }  匹配代码块和命令代码块:/pattern/匹配代码块,pattern可以是字符串或正则表达式;{ commands } 命令代码块,commadns可包含一条或多条命令。

    END{ commands }   结尾代码块:在对每一行进行处理之后再执行的代码块,主要是进行最终的计算或输出结尾摘要信息。

    awk工作原理:

    第一步:执行BEGIN{ commands }语句块中的语句,可以选择[-F|-f|-v]参数选项一起执行。

    第二步:从文件或标准输入(stdin)读取一行,然后执行/pattern/{ commands }语句块,它逐行扫描文件,从第一行到最后一行重复这个过程,直到文件全部被读取完毕。

    第三步:当读至输入流末尾时,执行END{ commands }语句块。

    BEGIN语句块在awk开始从输入流中读取行之前被执行,比如变量初始化、打印输出表格的表头等语句通常可以写在BEGIN语句块中,可以选择[-F|-f|-v]参数选项一起使用,这两部分是可选的。

    pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供/pattern/语句块,则默认执行{ commands },即打印每一个读取到的行,awk读取的每一行都会执行该语句块。

    END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中完成,它也是可选的。

    范例:以#号为分格符,分别输出两行,$1代表第一个字段,$2代表第二个字段。

    [root@cloucentos6 ~]# echo -e "A line 1#A line 2" | awk -F "#" 'BEGIN{ print "Start" } {print $1 " " $2} END{ print "End" }'

    Start

    A line 1

    A line 2

    End

    7.2awk内置变量

    awk有许多内置变量用来设置环境信息,这些变量可以被改变,下面给出了最常用的一些变量。如下图所示:

    举例:

    Linux系统创建了一个测试文本list,后续部分范例操作会以文本list为测试文件,测试文本list内容如下:

    [root@cloucentos6 home]# cat list

    John Daggett, 341 King Road, Plymouth MA

    Alice Ford, 22 EAST Broadway, Richmond VA

    Orville Thomas, 11345 Oak Bridge Road, Tulsa OK

    Terry Kalkas, 402 Lans Road, Beaver Falls PA

    Eric Adams, 20 Post Road, Sudbury MA

    Hubert Sims, 328A Brook Road, Roanoke VA

    Amy Wilde, 334 Bayshore Pkwy, Mountain View CA

    Sal Carpenter, 73 6th Street, Boston MA

    范例1$1显示第一列,awk如果没有指定分界符,默认以空格或制表符为分界符。

    [root@cloucentos6 home]# awk  '{print $1}'  list

    John

    Alice

    Orville

    Terry

    Eric

    Hubert

    Amy

    Sal

    知识点补充:$2代表第二列,以此类推,如果是$10以上,不能直接使用$10需要加上括号如:$(10)

    范例2$0输出当前文本内容。

    [root@cloucentos6 home]# awk  '{print $0}'  list

    John Daggett, 341 King Road, Plymouth MA

    Alice Ford, 22 EAST Broadway, Richmond VA

    Orville Thomas, 11345 Oak Bridge Road, Tulsa OK

    Terry Kalkas, 402 Lans Road, Beaver Falls PA

    Eric Adams, 20 Post Road, Sudbury MA

    Hubert Sims, 328A Brook Road, Roanoke VA

    Amy Wilde, 334 Bayshore Pkwy, Mountain View CA

    Sal Carpenter, 73 6th Street, Boston MA

    范例3使用NR统计文本中的行数,打印指定的行和列。

    [root@cloucentos6 home]# awk  '{print NR}'  list

    1

    2

    3

    4

    5

    6

    7

    8

    [root@cloucentos6 home]# awk  'END{print NR}'  list

    8

    [root@cloucentos6 home]# nl list | awk 'NR==3{print}'

         3     Orville Thomas, 11345 Oak Bridge Road, Tulsa OK

    [root@cloucentos6 home]# nl list | awk 'NR==3{print $2}'

    Orville

    范例4”/ /”模式,主要用于匹配正则表达式

    [root@cloucentos6 home]# awk '/MA/' list

    John Daggett, 341 King Road, Plymouth MA

    Eric Adams, 20 Post Road, Sudbury MA

    Sal Carpenter, 73 6th Street, Boston MA

    [root@cloucentos6 home]# awk '/MA/ {print $1}' list

    John

    Eric

    Sal

    范例5选项 –F 指定字段的分隔符

    [root@cloucentos6 home]# awk -F ',' '{print $1 $2}' list

    John Daggett 341 King Road

    Alice Ford 22 EAST Broadway

    Orville Thomas 11345 Oak Bridge Road

    Terry Kalkas 402 Lans Road

    Eric Adams 20 Post Road

    Hubert Sims 328A Brook Road

    Amy Wilde 334 Bayshore Pkwy

    Sal Carpenter 73 6th Street

    [root@cloucentos6 home]# awk -F ',' '{print $1;print $2}' list

    John Daggett

     341 King Road

    Alice Ford

     22 EAST Broadway

    Orville Thomas

     11345 Oak Bridge Road

    Terry Kalkas

     402 Lans Road

    Eric Adams

     20 Post Road

    Hubert Sims

     328A Brook Road

    Amy Wilde

     334 Bayshore Pkwy

    Sal Carpenter

     73 6th Street

    知识点补充:多重命令使用分号隔开。

    范例6选项 –f 直接调用脚本或文本里的内容

    [root@cloucentos6 home]# cat filename

    /MA/{print "第" NR "行:"  "内容:" $0}

    [root@cloucentos6 home]# awk -f filename list

    第1行:内容:John Daggett, 341 King Road, Plymouth MA

    第5行:内容:Eric Adams, 20 Post Road, Sudbury MA

    第8行:内容:Sal Carpenter, 73 6th Street, Boston MA

    范例7内置变量NF,NF显示文本每一行的字段数量,$NF显示文本最后一列。

    [root@cloucentos6 home]# awk '{print $NF}' list

    MA

    VA

    OK

    PA

    MA

    VA

    CA

    MA

    [root@cloucentos6 home]# awk '{print NF}' list

    7

    7

    8

    8

    7

    7

    8

    7

    范例8借助-v选项,可以将变量的值传递给awk,有两种传递方法。

    方法一:

    [root@cloucentos6 home]# cat test.sh

    #!/bin/bash

    var=1000

    echo | awk -v vartable=$var '{print vartable}'

    [root@cloucentos6 home]# ./test.sh

    1000

    方法二:

    [root@cloucentos6 home]# cat test.sh

    #!/bin/bash

    var1=1000

    var2=2000

    echo | awk '{print v1,v2}' v1=$var1 v2=$var2

    [root@cloucentos6 home]# ./test.sh

    1000 2000

    范例9向脚本传递参数

    [root@cloucentos6 home]# cat test.sh

    #!/bin/bash

    #在awk命令中$1代表输入行的第一列字段,而在shell脚本中$1代表命令行提供的第一个参数

    #把shell脚本$1第一个参数赋值给var,再将var赋值给awk$1第一列字段

    awk '$1=var' var=$1 list

    [root@cloucentos6 home]# ./test.sh  ABC

    ABC Daggett, 341 King Road, Plymouth MA

    ABC Ford, 22 EAST Broadway, Richmond VA

    ABC Thomas, 11345 Oak Bridge Road, Tulsa OK

    ABC Kalkas, 402 Lans Road, Beaver Falls PA

    ABC Adams, 20 Post Road, Sudbury MA

    ABC Sims, 328A Brook Road, Roanoke VA

    ABC Wilde, 334 Bayshore Pkwy, Mountain View CA

    ABC Carpenter, 73 6th Street, Boston MA

    范例10awk命令嵌套if判断语句和for循环语句。

    ###判断当前文件和目录大于500字节的文件打印出文件和大小

    [root@cloucentos6 home]# ls -l | awk '{if (($5>=500)) print " " "文件: " $9 " " "大小: " $5 "B" " "}'

    文件: lost+found

    大小: 16384B

    ###判断当前目录文本大于300字节的文件打印出文件和大小

    [root@cloucentos6 home]# ls -l | awk '{if (( $5>=300 && /^-/ )) print " " "文本: " $9 " " "大小: " $5 "B" " "}'

    文本: list

    大小: 341B

    文本: list.bak

    大小: 341B

    #把abcde字符串按顺序逐个输出

    [root@cloucentos6 home]# echo "abcde" | awk -F '' '{for(i=1;i<=NF;i++) print $i}'

    a

    b

    c

    d

    e

    [root@cloucentos6 home]# echo "abcde" | awk -F '' '{for(i=NF;i>=1;i--) print $i}'

    e

    d

    c

    b

    a

    范例11awk命令提供两个函数用于完成字符串大小写转换,函数为小写tolower()和大写toupper()。

    [root@cloucentos6 home]# awk '{print tolower($0)}' list

    john daggett, 341 king road, plymouth ma

    alice ford, 22 east broadway, richmond va

    orville thomas, 11345 oak bridge road, tulsa ok

    terry kalkas, 402 lans road, beaver falls pa

    eric adams, 20 post road, sudbury ma

    hubert sims, 328a brook road, roanoke va

    amy wilde, 334 bayshore pkwy, mountain view ca

    sal carpenter, 73 6th street, boston ma

    [root@cloucentos6 home]# awk '{print toupper($0)}' list

    JOHN DAGGETT, 341 KING ROAD, PLYMOUTH MA

    ALICE FORD, 22 EAST BROADWAY, RICHMOND VA

    ORVILLE THOMAS, 11345 OAK BRIDGE ROAD, TULSA OK

    TERRY KALKAS, 402 LANS ROAD, BEAVER FALLS PA

    ERIC ADAMS, 20 POST ROAD, SUDBURY MA

    HUBERT SIMS, 328A BROOK ROAD, ROANOKE VA

    AMY WILDE, 334 BAYSHORE PKWY, MOUNTAIN VIEW CA

    SAL CARPENTER, 73 6TH STREET, BOSTON MA

    范例12awk命令提供一个统计字符串长度的函数length()。

    [root@cloucentos6 home]# echo "abcde" | awk '{print length($0)}'

    5

    [root@cloucentos6 home]# echo "abcde" | awk -F '' '{print NF}'

    5

    [root@cloucentos6 home]# echo "abcde" | wc -L

    5

    [root@cloucentos6 home]# cat test.sh

    #!/bin/bash

    var="abcde"

    echo ${#var}

    [root@cloucentos6 home]# ./test.sh

    5

  • 相关阅读:
    原生js大总结十一
    jQuery快速入门知识重点
    原生js大总结九
    原生js大总结十
    原生js大总结八
    原生js大总结六
    原生js大总结七
    原生js大总结四
    原生js大总结五
    移动端适配
  • 原文地址:https://www.cnblogs.com/zoulongbin/p/6905290.html
Copyright © 2020-2023  润新知