awk编程

1. awk

    awk是操作数据并创建报告的语言。

    awk可以在命令行使用简单的运算符,也可以用于高级程序。awk可以操作数据,是shell脚本不可或缺的工具,也用于管理低级数据库。

[qwe@localhost ~]$ whereis awk
awk: /bin/awk /usr/bin/awk /usr/libexec/awk /usr/share/awk /usr/share/man/man1/awk.1.gz /usr/share/man/man1p/awk.1p.gz
[qwe@localhost ~]$ which awk
/usr/bin/awk
[qwe@localhost ~]$ awk --version
GNU Awk 3.1.7
Copyright (C) 1989, 1991-2009 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.
 

2.awk编程格式

    进行awk编程的时候,先输入awk指令,然后输入带单引号的模式或动作,最后输入文件。

    2.1 从文件输入

     [qwe@localhost awk]$ cat awkfile 
     洪  吉童  3324 5/11/96 50354
     林  巨正  5246 15/9/66 287650
     李  成桂  7654 6/20/58 60000
     丁  若涌  8683 9/40/48 365000

    [qwe@localhost awk]$ awk '{print $1, $2}' awkfile 
    洪 吉童
    林 巨正
    李 成桂
    丁 若涌
    [qwe@localhost awk]$ awk '{print $5}' awkfile 
    50354
    287650
    60000
    365000

    2.2 从指令输入

    使用“|”管道,可以从指令输入。

    [qwe@localhost awk]$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda2       18306828 3260180  14116704  19% /
tmpfs             515264     228    515036   1% /dev/shm
/dev/sda1         297485   32799    249326  12% /boot
[qwe@localhost awk]$ df | awk '$4>1000000'
Filesystem     1K-blocks    Used Available Use% Mounted on
/dev/sda2       18306828 3260172  14116712  19% /

   2.3  awk工作原理

   * 首先,awk通过文件或管道获取输入行,然后向$0内置变量输入行。各行称为“记录”。

   * 然后,行以空格分隔为每个字段或词。各字段保存为变量并赋予编号,从$1开始。能够保存超过100个字段。

   * awk有个叫作“FS内置变量”的字段分隔符,FS最先分配空格。若使用冒号或者别的符号分隔字段,则可以由新字段分隔符更改FS的值。

    * awk使用print函数在画面上显示字段。

    * 画面上显示awk后,调用文件的下一行,并保存为$0。此时,覆盖之前保存在$0变量的行,再用空格分隔字段进行处理。

    2.4 print函数

        awk命令的动作部分使用花括号({ })。若未指定动作而匹配模式,awk就执行默认动作,在屏幕上显示匹配行。使用print函数显示内容时无需格式化。

         awk动作部分中,print函数可以使用{print}格式。print函数可以使用参数变量计算出的值或字符串常数,字符串需使用双引号(“ ”)。

        [qwe@localhost awk]$ date
        Sun Apr 12 00:50:24 PDT 2020
        [qwe@localhost awk]$ date | awk '{print "Today is " $1 "day" "现在时间" $4 }'
        Today is Sunday现在时间00:51:46


   print函数的转义字符:

        \b            退格

        \f             换页符

        \n            newline下一行

        \r             回车

        \t              Tab

        \c             c代表字符

    2.5  OFMT变量  

        显示数字需要控制数字格式,可以使用printf函数,也可以使用OFMT变量。使用print函数时,可以利用OFMT变量控制数字显示格式。默认格式设置为%.6g,该格式最多包括6位数,若以“0.”开始则显示小数点后面的6位数,否则显示6位数。

[qwe@localhost awk]$ awk 'BEGIN{print 0.1234556,15E-3}'
0.123456 0.015
[qwe@localhost awk]$ awk 'BEGIN{print 1.23394944043}'
1.23395
[qwe@localhost awk]$ awk 'BEGIN{OFMT="%.2f";print 1.2333,15E-3}'
1.23 0.01

    2.6 printf函数

        printf函数通过标准输出返回已格式化字符串。printf语句拥有格式指示符和修饰符等控制字符串,控制字符串由逗号和逗号分隔的表达式的目录决定。

       printf格式字符:

       c                字符

       s                字符串

       d                十进制数

       ld                Long十进制数

       u                 Unsigned十进制数

       x                 16进制数

       lx                 Long 16进制数

       o                  八进制数

       lo                  Long八进制数

        e                  指定的批注中的实数

        f                    实数

        g                   即使输入使用e或f的实数也包含空格

[qwe@localhost awk]$ awk '{printf "The name is %-20s Number is %4d\n",$1" "$2,$3}' awkfile 
The name is 洪 吉童                 Number is 3324
The name is 林 巨正                 Number is 5246
The name is 李 成桂                 Number is 7654
The name is 丁 若涌                 Number is 8683

 “%-20”,表示从左侧开始显示20个字符。

    2.7 awk -f 选项

         若文件中已生成awk动作和命令,则使用-f选项。awk命令保存在特定文件中,使用-f选项在该文件中使用输入命令处理其他文件。格式:awk  -f  [awk命令文件][awk命令适用文本文件]

    2.8 记录和字段

        awk不能查看输入数据,但可以查看格式和结构。默认每行称为“记录”,由newline分隔。

        记录分隔符:默认设置的输出和输入记录分隔符是回车,保存在内置awk变量ORS和RS中。虽然可以更改,但最好不这么做。

        $0变量:awk中的所有记录都被浏览为$0.

        [qwe@localhost awk]$ awk '{print $0}' awkfile
        洪  吉童  3324 5/11/96 50354
        林  巨正  5246 15/9/66 287650
        李  成桂  7654 6/20/58 60000
        丁  若涌  8683 9/40/48 365000

         NR变量:每个记录号保存于awk内置变量NR。记录保存后,NR值就加1。

         [qwe@localhost awk]$ awk '{print NR,$0}'  awkfile 
         1 洪  吉童  3324 5/11/96 50354
         2 林  巨正  5246 15/9/66 287650
         3 李  成桂  7654 6/20/58 60000
         4 丁  若涌  8683 9/40/48 365000

         字段:每个记录默认由词构成,所谓的词由空格或者Tab分隔的字段组成,每个词称为1个字段。awk保持内置变量NF的字段数,每行NF值一般可拥有100个字段。
         [qwe@localhost awk]$ awk '{print $0,NF}' awkfile 
         洪  吉童  3324 5/11/96 50354 5
         林  巨正  5246 15/9/66 287650 5
         李  成桂  7654 6/20/58 60000 5
         丁  若涌  8683 9/40/48 365000 5

       字段分隔符:awk内置变量FS拥有输入字段分隔符的值。

     2.9 模式和动作
          模式:awk模式管理awk在输入行的动作,该模式由正则表达式、真和假状态结果或二者结合组成。

          动作:awk动作是使用花括号({ })的语句,以分号分隔。模式在动作之前,动作可创建为简单语句或高级语句组。


  3. 正则表达式

          awk支持的元字符如下:

          ^              匹配字符串的开头

          $              匹配字符串的末尾

          .               匹配1个字符

          *               匹配0及0个以上字符

          +               匹配1个及多个字符

          -                匹配0个或1个字符

          [ABC]        匹配其中一个字符

           [^ABC]       之中无匹配字符

           [A-Z]           A-Z范围内存在匹配字符

           A|B             匹配A或B

          (AB)+     匹配多个AB字符集

            \*               匹配(*)字符

           &                在检索字符串中用检索出的字符串代替

        match运算符:标记波浪线(~)的match运算符检查某个记录或字段是否匹配表达式。

            [qwe@localhost awk]$ awk '$2~ /[Jj]itong/' awkfile2
            hong jitong 3324 5/11/96 50354


    5. 比较表达式

         比较表达式检索的行只有在状态显示为真时才能执行动作,该表达式使用关系运算符比较数字或字符串。

         <                小于

        <=               小于等于

        ==                等于

        !=              不等于

         >=               大于等于

         >                 大于

         ~                 匹配正则表达式

         !~              与正则表达式不匹配

         算术运算符如下:

          +         加法                 -    减法                 *    乘法             /       除法

           %       取余                 ^    乘方

         逻辑运算符和混合模式

          &&     逻辑和             ||     逻辑或               !         逻辑非

 

     6. awk变量

       6.1   数值与字符串常数

               数值分为123等整数型和3.14等实数型,也可以使用.123E-1或1.2e3等科学符号。

               awk程序可添加变量。字符串、数字、数字和字符结合的值都能成为变量。若没有变量,则成为“=”符号右侧表达式的类型。

         6.2   用户自定义变量

                awk不会另外定义用户自定义变量,但可在表达式中根据变量上下文预测数据类型。若不初始化变量,awk就将字符串         变量和数字型变量分别初始化为null和0。

              增量运算符(++)和减量运算符(--)

              命令行的用户自定义变量:可以在命令行给变量分配值,并传递给awk脚本。

              awk -f awkfile -v month=8 year=2008 filename

              字段变量:除参考字段之外,字段变量可用作用户自定义变量。通过分配值可以创建新字段,若可以浏览字段值且不赋值,则分配null字符串。

              awk '{$3=100 * $2/$1; print }'  filename    //文件不存在$3则创建,如果存在则覆盖原来的值

        6.3 BEGIN模式

              awk处理处输文件的行之前执行BEGIN模式,将其置于动作块前。若awk未完成BEGIN动作块,则BEGIN块不读取输入内容,所以输入文件不存在也可测试。

             BEGIN动作通常用于更改内置变量(OFS、RS、FS等)、分配用户自定义变量的初始值,并常作为输出的一部分用于打印头文件或标题。

         6.4 END模式

               END模式不输入任何输入行,但执行END模式相关动作。先处理所有输入行,然后处理END模式。

7. awk重定向  

      输出重定向: 将awk的结果重定向至Linux文件时,使用shell重定向运算符。但是,此文件名必须使用双引号。

       [qwe@localhost awk]$ awk -F: '$5 >= 100000 {print $1,$2 > "newfile"}' awkfile

      输入重定向:使用getline函数从标准输入、管道、当前处理的文件读取输入内容。在输入的下一行设置NF、NR、FNR内置变量。getline函数检索到记录则返回1,检索文件末尾则返回0。若发生错误,getline函数返回-1,表示文件打开失败。

         [qwe@localhost awk]$ awk 'BEGIN{ "date" | getline d;print d}'
        Sun Apr 12 03:02:51 PDT 2020

       //执行linux指令date,用管道连接命令结果。然后向用户自定义变量d分配getline的结果值,并显示d的值。

  8. awk管道

          在awk程序中打开管道时,打开其他管道前先关闭已打开的管道。管道符号右侧命令必须使用双引号(“ ”)。每个管道只能打开一次。

[qwe@localhost awk]$ awk '{print $1,$2 | "sort -r"}' cars             //sort命令使用-r选项,表示逆序排列。
zsdddd 
sonate 
qwelss 
pride 
m5 
[qwe@localhost awk]$ cat cars
m5
sonate
qwelss
zsdddd
pride 

       关闭文件和管道:需要关闭第一个管道才能重新读写awk程序的文件或管道,因为脚本结束前会一直保持打开状态。文件或管道一旦打开就会一直保持开启状态,直到awk终止,所以end块的语句受管道影响。

     system函数:内置函数执行包含参数的Linux系统命令,并向awk程序返回终止状态。

     system("Linux 指令")

 9. 程序管理语句

      9.1 next语句

          next语句从输入文件获取输入的下一行,从awk脚本开始部分重新执行。

          [qwe@localhost awk]$ awk -f awkscript3 awkdata1 
Tom    85    88
Mary   74    98
[qwe@localhost awk]$ cat awkdata1 
Tom    85    88
Jane   91    -1
Mary   74    98
[qwe@localhost awk]$ cat awkscript3 
{
if ($1~/Jane/){next}
  else {print}
}

     9.2 exit函数

          使用exit函数终止awk语句,但只暂停记录处理,不略过end语句。exit函数的参数值范围是0-255,根据参数确定终止状态。终止状态变量为0表示正常终止,非0表示非正常终止。

 

 10.数组

     10.1 用作数组索引的变量

      [qwe@localhost awk]$ awk '{id[NR]=$3};END{for(x = 1;x <= NR;x++)\>print id[x]}' awkdata1

     10.2  特殊for循环语句

        特殊for循环语句用于以下情况:子脚本为字符串、子脚本非连续数字、for循环语句不能使用而通过关联数组读取。

       {

       for(数组项目){

         print 数组名 [项目]

       }

        }

     10.3  用作数组子脚本的字符串

         子脚本包含的变量拥有字符串或常数字符串,常数字符串必须使用双引号(“ ”)。

      10.4  用作数组子脚本的字段值

          数组中的表达式可用作子脚本,所以字段也可用作子脚本。

          for (数组的索引值)  语句

       10.5 数组和split函数

           awk的内置函数split函数截取保存于词和数组的字符串。

           [qwe@localhost awk]$ awk 'BEGIN{ split("7/21/2009",date,"/");delete date[3];print "今天                                                       是"date[3]"年"date[1]"月"date[2]"日"}'
今天是年7月21日

        10.6 delete函数

             函数清除数组要素。

        10.7  多维数组

              awk默认不支持多维数组,但提供多维格式相关语法,也就是将索引与字符串进行连接的方法。

 

  11. 命令处理参数

          ARGV:awk中名为ARGV的内置数组可用作命令行参数,该参数包含awk命令,但是不能向awk传递任何选项。ARGV数组从0开始。

        ARGC:ARGC是内置变量,代表命令行参数的个数。

 

   12.awk内置函数

        12.1 字符串函数

          sub函数:在记录中检索匹配正则表达式的字符串,并替换为需要的字符串。

           sub(正则表达式,需要替换的字符串);

           sub (正则表达式,需要替换的字符串,目标字符串)

       [qwe@localhost awk]$ awk '{sub(/li/,"HI");print}' awkfile2
hong jitong 3324 5/11/96 50354
HIn  kilnit 5246 15/9/66 287650
HI   cehnggui 7654 6/20/58 60000

         index函数:返回在字符串中首次发现substring的位置。

        index(string,substring)

       [qwe@localhost awk]$ awk 'BEGIN{ print index("hello","lo")}'
       4

       length函数:返回字符串中的字符数。

       substr函数:从已有字符串截取至指定的开始位置之前的全部内容,然后返回剩余字符串。

       substr(字符串,开始位置)

       substr(字符串,开始位置,字符串长度)

      [qwe@localhost awk]$ awk 'BEGIN{print substr("subta clasus",7,6)}'
      clasus
      [qwe@localhost awk]$ awk 'BEGIN{print substr("subta clasus",7,3)}'
      cla

       match函数:返回正则表达式的字符串所在索引位置,查询失败就返回0.

       match (字符串,正则表达式)

      [qwe@localhost awk]$ awk 'BEGIN{start=match("CentOS LINUX",/[A-Z]+$/);print start}'
     8   

      split函数:使用第三个参数的字段分隔符截取数组的字符串。

      split(字符串,数组,字段分隔符)

      split(字符串,数组)

      sprintf函数:返回指定形式的表达式。

      变量=sprintf(“格式指定形式的字符串”,表达式1,表达式2,表达式3)

   12.2  数学函数

      整数型函数:int函数将指定数据转为整数型。

 [qwe@localhost awk]$ awk 'END{print 32/3}' awkfile6
10.6667
[qwe@localhost awk]$ awk 'END{print int(32/3)}' awkfile6
10

     rand函数:生成大于0小于1的实数。

     srand函数:无参数的函数可使用时间创建srand函数的种子。

     [qwe@localhost awk]$ awk 'BEGIN{srand()};{print rand()}' awkfile6

  12.3 时间函数

     systime函数:返回1970年1月1日至当前时间范围内的时间(精确到秒)。

     strftime函数:时间戳,从systime返回。

     strftime([format specification][,timestamp])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值