gawk进阶

Posted tianmu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gawk进阶相关的知识,希望对你有一定的参考价值。

#使用变量
    一、内建变量
        1. 字段和记录分隔符变量
            gawk数据字段和记录变量
            变 量            描 述
            FIELDWIDTHS      由空格分隔的一列数字,定义了每个数据字段确切宽度
            FS               输入字段分隔符
            RS               输入记录分隔符
            OFS              输出字段分隔符
            ORS              输出记录分隔符
            FS与OPS的使用
                $ cat data1
                data11,data12,data13,data14,data15
                data21,data22,data23,data24,data25
                data31,data32,data33,data34,data35
                $ gawk ‘BEGINFS="," print $1,$2,$3‘ data1    -- 默认情况下,gawk将 OFS 设成一个空格
                data11 data12 data13
                data21 data22 data23
                data31 data32 data33
                $ gawk ‘BEGINFS=","; OFS="-" print $1,$2,$3‘ data1    -- 修改输出分隔符值
                data11-data12-data13
                data21-data22-data23
                data31-data32-data33
            FIELDWIDTHS 变量定义了四个字段,根据已定义好的字段长度来分割
                $ cat data1b
                1005.3247596.37
                115-2.349194.00
                05810.1298100.1
                $ gawk ‘BEGINFIELDWIDTHS="3 5 2 5"print $1,$2,$3,$4‘ data1b
                100 5.324 75 96.37
                115 -2.34 91 94.00
                058 10.12 98 100.1
            RS与ORS的使用:默认情况下,gawk将 RS 和 ORS 设为换行符
                $ cat data2
                Riley Mullen
                123 Main Street
                Chicago, IL 60601
                (312)555-1234
                
                Frank Williams
                456 Oak Street
                Indianapolis, IN 46201
                (317)555-9876
                
                Haley Snell
                4231 Elm Street
                Detroit, MI 48201
                (313)555-4938
                $ gawk ‘BEGINFS="\n"; RS="" print $1,$4‘ data2    -- 现在gawk把文件中的每行都当成一个字段,把空白行当作记录分隔符
                Riley Mullen (312)555-1234
                Frank Williams (317)555-9876
                Haley Snell (313)555-4938
        2. 数据变量
            更多的gawk内建变量
            变 量           描 述
            ARGC            当前命令行参数个数
            ARGIND          当前文件在 ARGV 中的位置
            ARGV            包含命令行参数的数组
            CONVFMT         数字的转换格式(参见 printf 语句),默认值为 %.6 g
            ENVIRON         当前shell环境变量及其值组成的关联数组
            ERRNO           当读取或关闭输入文件发生错误时的系统错误号
            FILENAME        用作gawk输入数据的数据文件的文件名
            FNR             当前数据文件中的数据行数
            IGNORECASE      设成非零值时,忽略 gawk 命令中出现的字符串的字符大小写
            NF              数据文件中的字段总数
            NR              已处理的输入记录数
            OFMT            数字的输出格式,默认值为 %.6 g
            RLENGTH         由 match 函数所匹配的子字符串的长度
            RSTART          由 match 函数所匹配的子字符串的起始位置
            ARGC与ARGV
                $ gawk ‘BEGINprint ARGC,ARGV[1]‘ data1  -- ARGC 变量表明命令行上有两个参数。 ARGV 数组从索引 0 开始。
            ENVIRON 变量,使用关联数组来提取shell环境变量
                $ gawk ‘
                > BEGIN
                > print ENVIRON["HOME"]
                > print ENVIRON["PATH"]
                > ‘
                /home/rich
                /usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin
             NF 变量可以让你在不知道具体位置的情况下指定记录中的最后一个数据字段
                $ gawk ‘BEGINFS=":"; OFS=":" print $1,$NF‘ /etc/passwd    -- 
                rich:/bin/bash
                testy:/bin/csh
                mark:/bin/bash
                dan:/bin/bash
                mike:/bin/bash
                test:/bin/bash
            FNR 和 NR 变量虽然类似,但又略有不同。
                $ gawk ‘
                > BEGIN FS=","
                > print $1,"FNR="FNR,"NR="NR
                > ENDprint "There were",NR,"records processed"‘ data1 data1  
                data11 FNR=1 NR=1
                data21 FNR=2 NR=2
                data31 FNR=3 NR=3
                data11 FNR=1 NR=4    -- FNR 变量的值在 gawk 处理第二个数据文件时被重置了,而 NR 变量则在处理第二个数据文件时继续计数。
                data21 FNR=2 NR=5
                data31 FNR=3 NR=6
                There were 6 records processed
                2 data1
    二、自定义变量
        gawk自定义变量名可以是任意数目的字母、数字和下划线,但不能以数字开头。注意: gawk 变量名区分大小写!
        1. 在脚本中给变量赋值(值可以是数字、文本,赋值支持数学算式)
            $ gawk ‘
            > BEGIN
            > testing="This is a test"
            > print testing
            > testing=45
            > print testing
            > ‘
            This is a test
            45    
            $ gawk ‘BEGINx=4; x= x * 2 + 3; print x‘
            11    
        2. 在命令行上给变量赋值
            $ cat script1
            BEGINFS=","
            print $n
            $ gawk -f script1 n=2 data1    -- 显示了文件的第二个数据字段
            data12
            data22
            data32
            用 -v 命令行参数,它允许你在 BEGIN 代码之前设定变量,否则设定的变量值在begin部分不可用。-v 命令行参数必须放在脚本代码之前。
            $ gawk -v n=3 -f script2 data1
            The starting value is 3
            data13
            data23
            data33            
#处理数组
    定义数组变量
        格式:var[index] = element  其中 var 是变量名,index 是关联数组的索引值,element 是数据元素值
            $ gawk ‘BEGIN
            > capital["Illinois"] = "Springfield"
            > print capital["Illinois"]
            > ‘
            Springfield
            $
            $ gawk ‘BEGIN
            > var[1] = 34
            > var[2] = 3
            > total = var[1] + var[2]
            > print total
            > ‘
            37        
    遍历数组变量
        gwak遍历格式:
            for (var in array)
            
                statements
            
        变量中存储的是索引值而不是数组元素值
            $ gawk ‘BEGIN
            > var["a"] = 1
            > var["g"] = 2
            > var["m"] = 3
            > var["u"] = 4
            > for (test in var)
            > 
            > print "Index:",test," - Value:",var[test]
            > 
            > ‘
            Index: u - Value: 4
            Index: m - Value: 3
            Index: a - Value: 1
            Index: g - Value: 2            
    删除数组变量
        格式:delete array[index]
        删除命令会从数组中删除关联索引值和相关的数据元素值
            $ gawk ‘BEGIN
            > var["a"] = 1
            > var["g"] = 2
            > for (test in var)
            > 
            > print "Index:",test," - Value:",var[test]
            > 
            > delete var["g"]
            > print "---"
            > for (test in var)
            > print "Index:",test," - Value:",var[test]
            > ‘
            Index: a - Value: 1
            Index: g - Value: 2
            ---
            Index: a - Value: 1
#使用模式
    正则表达式
        正则表达式必须出现在它要控制的程序脚本的左花括号前
            $ gawk ‘BEGINFS="," /11/print $1‘ data1
            data11
    匹配操作符
        匹配操作符是波浪线( ~ ),允许将正则表达式限定在记录中的特定数据字段
            $ gawk –F: ‘$1 !~ /rich/print $1,$NF‘ /etc/passwd    -- gawk程序脚本会打印/etc/passwd文件中与用户ID  rich 不匹配的用户ID和登录shell
            root /bin/bash
            daemon /bin/sh
            bin /bin/sh
            sys /bin/sh
            $ gawk -F: ‘$1 ~ /rich/print $1,$NF‘ /etc/passwd
            rich /bin/bash
            $ gawk ‘BEGINFS="," $2 ~ /^data2/print $0‘ data1
            data21,data22,data23,data24,data25
    数学表达式
        可以使用任何常见的数学比较表达式。
            x == y :值x等于y。
            x <= y :值x小于等于y。
            x < y :值x小于y。
            x >= y :值x大于等于y。
            x > y :值x大于y。
            $ gawk -F: ‘$4 == 0print $1‘ /etc/passwd    -- 显示所有属于root用户组(组ID为 0 )的系统用户
            root
            sync
            shutdown
            halt
            operator
        也可以对文本数据使用表达式,跟正则表达式不同,表达式必须完全匹配
            $ gawk -F, ‘$1 == "data"print $1‘ data1
            $
            $ gawk -F, ‘$1 == "data11"print $1‘ data1
            data11
#结构命令
    if语句
        gawk编程语言支持标准的 if-then-else 格式的 if 语句。你必须为 if 语句定义一个求值的条件,并将其用圆括号括起来
        格式:if (condition) statement1
            $ cat data4
            10
            5
            13
            50
            34
            $ gawk ‘if ($1 > 20) print $1‘ data4
            50
            34
            $ gawk ‘
            > if ($1 > 20)
            >     -- 执行多条语句,就必须用花括号将它们括起来
            > x = $1 * 2
            > print x
            > 
            > ‘ data4
            100
            68
        gawk 的 if 语句也支持 else 子句,允许在 if 语句条件不成立的情况下执行一条或多条语句
            $ gawk ‘
            > if ($1 > 20)
            > 
            > x = $1 * 2
            > print x
            >  else
            > 
            > x = $1 / 2
            > print x
            > ‘ data4
            5
            2.5
            6.5
            100
            68
    while语句
        while 循环允许遍历一组数据,并检查迭代的结束条件
        格式:
            while (condition)
            
                statements
            
            $ cat data5
            130 120 135
            160 113 140
            145 170 215
            $ gawk ‘
            > total = 0
            > i = 1
            > while (i < 4)
            > 
            > total += $i
            > i++
            > 
            > avg = total / 3
            > print "Average:",avg
            > ‘ data5
            Average: 128.333
            Average: 137.667
            Average: 176.667
        gawk编程语言支持在 while 循环中使用 break 语句和 continue 语句,允许你从循环中跳出
            $ gawk ‘
            > total = 0
            > i = 1
            > while (i < 4)
            > 
            > total += $i
            > if (i == 2)
            > break
            > i++
            > 
            > avg = total / 2
            > print "The average of the first two data elements is:",avg
            > ‘ data5
            The average of the first two data elements is: 125
            The average of the first two data elements is: 136.5
            The average of the first two data elements is: 157.5
    do—while语句
        do-while 语句类似于 while 语句,但会在检查条件语句之前执行命令
        格式:
            do
            
                statements
             while (condition)
            $ gawk ‘
            > total = 0
            > i = 1
            > do
            > 
            > total += $i
            > i++
            >  while (total < 150)
            > print total ‘ data5
            250
            160
            315
    for语句
        gawk编程语言支持C风格的 for 循环
            格式:for( variable assignment; condition; iteration process)
                $ gawk ‘
                > total = 0
                > for (i = 1; i < 4; i++)
                > 
                > total += $i
                > 
                > avg = total / 3
                > print "Average:",avg
                > ‘ data5
                Average: 128.333
                Average: 137.667
                Average: 176.667
#格式化打印
    格式:printf "format string", var1, var2 . . .    
    format string 是格式化输出的关键它会用文本元素和格式化指定符来具体指定如何呈现格式化输出。格式化指定符是一种特殊的代码,会指明显示什么类型的变量以及如何显示。gawk程序会将每个格式化指定符作为占位符,供命令中的变量使用。第一个格式化指定符对应列出的第一个变量,第二个对应第二个变量,依此类推
    格式化指定符格式:%[modifier]control-letter  -- 其中 control-letter 是一个单字符代码,用于指明显示什么类型的数据
        格式化指定符的控制字母
        控制字母  描 述
        c         将一个数作为ASCII字符显示
        d         显示一个整数值
        i         显示一个整数值(跟d一样)
        e         用科学计数法显示一个数
        f         显示一个浮点值
        g         用科学计数法或浮点数显示(选择较短的格式)
        o         显示一个八进制值
        s         显示一个文本字符串
        x         显示一个十六进制值
        X         显示一个十六进制值,但用大写字母A~F    
        科学计数法显示一个数
            $ gawk ‘BEGIN
            > x = 10 * 100
            > printf "The answer is: %e\n", x
            > ‘
            The answer is: 1.000000e+03
        除了控制字母外,还有3种修饰符可以用来进一步控制输出:
            width :指定了输出字段最小宽度的数字值。如果输出短于这个值, printf 会将文本右对齐,并用空格进行填充。如果输出比指定的宽度还要长,则按照实际的长度输出。
            prec :这是一个数字值,指定了浮点数中小数点后面位数,或者文本字符串中显示的最大字符数。
            - (减号):指明在向格式化空间中放入数据时采用左对齐而不是右对齐。在使用 printf 语句时,你可以完全控制输出样式
                通过添加一个值为 16 的修饰符,我们强制第一个字符串的输出宽度为16个字符。默认情况下,printf 命令使用右对齐来将数据放到格式化空间中。要改成左对齐,只需给修饰符加一个减号即可            
                    $ gawk ‘BEGINFS="\n"; RS="" printf "%-16s %s\n", $1, $4‘ data2
                    Riley Mullen (312)555-1234
                    Frank Williams (317)555-9876
                    Haley Snell (313)555-4938
#内建函数
    数学函数
        gawk数学函数
            函 数        描 述
            atan2(x, y)  x/y的反正切,x和y以弧度为单位
            cos(x)       x的余弦,x以弧度为单位
            exp(x)       x的指数函数
            int(x)       x的整数部分,取靠近零一侧的值
            log(x)       x的自然对数
            rand( )      比0大比1小的随机浮点值
            sin(x)       x的正弦,x以弧度为单位
            sqrt(x)      x的平方根
            srand(x)    为计算随机数指定一个种子值
        gawk还支持一些按位操作数据的函数。
            and(v1, v2) :执行值 v1 和 v2 的按位与运算。
            compl(val) :执行 val 的补运算。
            lshift(val, count) :将值 val 左移 count 位。
            or(v1, v2) :执行值 v1 和 v2 的按位或运算。
            rshift(val, count) :将值 val 右移 count 位。
            xor(v1, v2) :执行值 v1 和 v2 的按位异或运算。
    字符串函数
        gawk字符串函数
        函 数                      描 述
        asort(s [,d])              将数组s按数据元素值排序。索引值会被替换成表示新的排序顺序的连续数字。另外,如果指定了d,则排序后的数组会存储在数组d中
        asorti(s [,d])             将数组s按索引值排序。生成的数组会将索引值作为数据元素值,用连续数字索引来表明排序顺序。另外如果指定了d,排序后的数组会存储在数组d中
        gensub(r, s, h [, t])      查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果h是一个以g或G开头的字符串,就用s替换掉匹配的文本。如果h是一个数字,它表示要替换掉第h处r匹配的地方
        gsub(r, s [,t])            查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串s
        index(s, t)                返回字符串t在字符串s中的索引值,如果没找到的话返回 0
        length([s])                返回字符串s的长度;如果没有指定的话,返回$0的长度
        match(s, r [,a])           返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配正则表达式的那部分
        split(s, a [,r])           将s用 FS 字符或正则表达式r(如果指定了的话)分开放到数组a中。返回字段的总数
        sprintf(format,variables)  用提供的format和variables返回一个类似于printf输出的字符串
        sub(r, s [,t])             在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配
        substr(s, i [,n])          返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回s剩下的部分
        tolower(s)                 将s中的所有字符转换成小写
        toupper(s)                 将s中的所有字符转换成大写
        转换大写,返回长度
            $ gawk ‘BEGINx = "testing"; print toupper(x); print length(x) ‘
            TESTING
            7        
        排序
            $ gawk ‘BEGIN
            > var["a"] = 1
            > var["g"] = 2
            > var["m"] = 3
            > var["u"] = 4
            > asort(var, test)
            > for (i in test)
            > print "Index:",i," - value:",test[i]
            > ‘
            Index: 4 - value: 4
            Index: 1 - value: 1
            Index: 2 - value: 2
            Index: 3 - value: 3        
    时间函数
        gawk的时间函数
        函 数                           描 述
        mktime(datespec)                将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳值 ①
        strftime(format[,timestamp])    将当前时间的时间戳或timestamp(如果提供了的话)转化格式化日期(采用shell函数date()的格式)              
        systime( )                      返回当前时间的时间戳
        例如:
            $ gawk ‘BEGIN
            > date = systime()
            > day = strftime("%A, %B %d, %Y", date)
            > print day
            > ‘
            Friday, December 26, 2014        
#自定义函数
    定义函数
        格式:
            function name([variables])
            
                statements
            
    使用自定义函数
        在定义函数时,它必须出现在所有代码块之前(包括 BEGIN 代码块),有助于将函数代码与gawk程序的其他部分分开
            $ gawk ‘
            > function myprint()
            > 
            > printf "%-16s - %s\n", $1, $4
            > 
            > BEGINFS="\n"; RS=""
            > 
            > myprint()
            > ‘ data2
            Riley Mullen - (312)555-1234
            Frank Williams - (317)555-9876
            Haley Snell - (313)555-4938
    创建函数库
        $ cat funclib
        function myprint()
        
            printf "%-16s - %s\n", $1, $4
        
        function myrand(limit)
        
            return int(limit * rand())
        
        function printthird()
        
            print $3
        
        $ cat script4
        BEGIN FS="\n"; RS=""
        
            myprint()
        
        $ gawk -f funclib -f script4 data2
        Riley Mullen - (312)555-1234
        Frank Williams - (317)555-9876
        Haley Snell - (313)555-4938
#实例
    计算保龄球锦标赛成绩
        $ cat scores.txt
        Rich Blum,team1,100,115,95
        Barbara Blum,team1,110,115,100
        Christine Bresnahan,team2,120,115,118
        Tim Bresnahan,team2,125,112,116
        $ cat bowling.sh
        for team in $(gawk –F, ‘print $2‘ scores.txt | uniq)
        do
            gawk –v team=$team ‘BEGINFS=","; total=0
        
        if ($2==team)
        
            total += $3 + $4 + $5;
        
        
        END 
            avg = total / 6;
            print "Total for", team, "is", total, ",the average is",avg
        ‘ scores.txt
        done
        $ sh bowling.sh
        Total for team1 is 635, the average is 105.833
        Total for team2 is 706, the average is 117.667

 

以上是关于gawk进阶的主要内容,如果未能解决你的问题,请参考以下文章

gawk进阶

Shell编程—gawk进阶

《Linux命令行与shell脚本编程大全》第二十二章 gawk进阶

awk进阶整理

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印出C++的函数耗时以及代码片段耗时详情

Atom编辑器入门到精通 Atom使用进阶