AWK的入门学习记录

AWK介绍及使用方法

预定义变量

  1. awk将程序的输入分为记录和字段。 它跟踪从当前输入文件到目前为止已读取的记录数。 该值存储在名为FNR的预定义变量中,每次启动新文件时该变量都将重置为零。 另一个预定义的变量NR记录了到目前为止已从所有数据文件读取的输入记录的总数。 它从零开始,但永远不会自动重置为零。

  2. NF:表示的是浏览记录的域(以空格为默认间隔符则表示列)的个数
    $NF :表示的最后一个Field(列),即输出最后一个字段的内容

  3. awk函数的split(s, a, sep)使用分隔符sep将字符串s拆分为数组a

  4. tail&cat

    tail 功能:显示指定文件的后若干行。
    语法:tail [+ / - num ] [参数] 文件
    tail命令中各个选项的含义为:
    +num 从第num行以后开始显示。- num 从距文件尾num行处开始显示。如果省略num参数,系统默认值为10。

    • l 以文本行为num的计数单位。与参数选项+num- num选项同时使用时,num表示要显示的文本行行数。
    • c 以字节为num的计数单位。与参数选项+num- num选项同时使用时,num表示要显示的字符数。(l、c选项可以省略,系统默认值为l,即按行计数)。
    • 使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不但刷新,使你看到最新的文件内容。

    cat主要有三大功能:

    • 一次显示整个文件。

      $ cat filename 
      
    • 从键盘创建一个文件。

      $ cat > filename 
      

      只能创建新文件,不能编辑已有文件.

    • 将几个文件合并为一个文件。

      $cat file1 file2 > file 
      
  5. paste的用法
    -d<间隔字符>或–delimiters=<间隔字符> :用指定的间隔字符取代跳格字符。
    在这里插入图片描述

AWK介绍

  • awk的基本功能是在文件中搜索包含某些模式的行(或其他文本单位)。 当一行与其中一种模式匹配时,awk在该行上执行指定的操作。 awk继续以这种方式处理输入行,直到到达输入文件的末尾。
  • awk中的程序与大多数其他语言中的程序不同,因为awk程序是数据驱动的(即,描述要使用的数据,然后找到要处理的数据)。 其他大多数语言都是程序性语言; 必须详细描述程序应采取的每个步骤。 使用过程语言时,通常很难清楚地描述程序将要处理的数据。 因此,awk程序通常很容易阅读和编写。
  • 当运行awk时,可以指定一个awk程序来告诉awk该怎么做。 该程序由一系列规则组成(它可能还包含函数定义,这是我们暂时将忽略的高级功能;请参阅 User-Defined Functions一节)。 每个规则指定一个要搜索的模式,并在找到该模式时执行一个动作。
  • 从句法上讲,规则由一个模式和一个动作组成。 该动作用大括号括起来,以将其与模式分开。 换行符通常是分开的规则。 因此,awk程序如下所示:
     pattern { action }
     pattern { action }
     … 
    

一些简单的例子

  • 以下命令运行一个简单的awk程序,该程序在输入文件mail-list中搜索字符串li(一组字符通常称为字符串;术语string基于英语中的类似用法,例如,a string of pearls or a string of cars in a train):

    awk '/li/ { print $0 }' mail-list
    

    当找到包含li的行时,将打印它们,因为print $0表示打印当前行。 (print本身就意味着同一含义,所以我们可以写成那个。)

    您会注意到,awk程序中的字符串li周围包含斜杠(/)。 斜线表示li 是要搜索的模式。 这种类型的模式称为正则表达式,稍后将对其进行详细介绍(请参见Regular Expressions)。 允许该模式匹配单词的各个部分。 awk程序周围有单引号,因此shell不会将其中的任何字符解释为特殊的shell字符。
    这是程序打印的内容:

    $ awk '/li/ { print $0 }' mail-list
    -| Amelia       555-5553     amelia.zodiacusque@gmail.com    F
    -| Broderick    555-0542     broderick.aliquotiens@yahoo.com R
    -| Julie        555-6699     julie.perscrutabor@skeeve.com   F
    -| Samuel       555-3430     samuel.lanceolis@shu.edu        A
    
  • awk规则中,可以省略模式或动作,但不能两者都省略。如果省略该模式,则对每个输入行执行该动作。如果省略该动作,则默认动作是打印与该模式匹配的所有行。因此,我们可以省略上一个示例中的操作(打印语句和花括号),结果将是相同的:awk打印所有与模式li匹配的行。相比之下,省略打印语句但保留花括号将执行一个不执行任何操作的空操作(即,不打印任何行)。许多实用的awk程序只有一两行。以下是一些有用的简短程序,可以帮助您入门。其中一些程序包含尚未涵盖的构造。以下大多示例都使用名为data的数据文件,这只是一个占位符;在自己的文件中需要替换为自己的文件名:

    • 打印每行超过80个字符的行:

      awk 'length($0) > 80' data
      

      在单一的规则将关系表达式作为其模式,并且不执行任何操作,因此它使用默认操作来打印记录。

    • 打印最长输入行的长度:

      awk '{ if (length($0) > max) max = length($0) }
      END { print max }' data
      

      与END关联的代码在所有输入被读取后执行;it’s the other side of the coin to BEGIN.

    • 打印data中最长行的长度:

      expand data | awk '{ if (x < length($0)) x = length($0) }
                  END { print "maximum line length is " x }'
      

      此示例与上一个示例稍有不同:输入是由expand实用程序处理的,将TAB更改为空格,因此,比较的宽度实际上是右边距列,而不是每行输入字符的数量。

    • 打印至少包含一个字段的每一行:

      awk 'NF > 0' data
      

      这是从文件中删除空白行的简便方法(或者,类似于旧文件创建一个新文件,但空白行已从中删除)。

    • 打印从0到100的七个随机数,包括100在内:

      awk 'BEGIN { for (i = 1; i <= 7; i++)
                 print int(101 * rand()) }'
      
    • 打印files使用的总字节数:

      ls -l files | awk '{ x += $5 }
                    END { print "total bytes: " x }'
      
    • 打印文件使用的千字节总数:

      ls -l files | awk '{ x += $5 }
         END { print "total K-bytes:", x / 1024 }'
      
    • 打印所有用户的登录名的排序列表:

      awk -F: '{ print $1 }' /etc/passwd | sort
      
    • 计算文件中的行数:

      awk 'END { print NR }' data
      
    • 打印data文件中的偶数行:

      awk 'NR % 2 == 0' data
      

      如果改用表达式NR%2 == 1,则程序将打印奇数行

两个规则的例子

  • awk实用程序一次只读取一行输入文件。 对于每一行,awk都会尝试每个规则的模式。 如果多个模式匹配,则几个动作将按照它们在awk程序中出现的顺序执行。 如果没有任何模式匹配,则不会执行任何操作。

  • 在处理了所有与该行匹配的规则(也许没有规则)之后,awk读取下一行。 (但是,请参阅The next Statement部分,另请参见The nextfile Statement部分。)这将一直持续到程序到达文件末尾为止。 例如,以下awk程序包含两个规则:

    /12/  { print $0 }
    /21/  { print $0 }
    

    第一条规则将字符串12作为模式,将print $ 0作为动作。 第二个规则以字符串21作为模式,还以print $ 0作为动作。 每个规则的动作都包含在其自己的大括号内。

    该程序将打印包含字符串12或字符串21的每一行。 如果一行包含两个字符串,则将其打印两次,每条规则打印一次。

    如果我们在两个示例数据文件(mail-listinventory-shipped)上运行此程序,则会发生这种情况:

    $ awk '/12/ { print $0 }
    >      /21/ { print $0 }' mail-list inventory-shipped
    -| Anthony      555-3412     anthony.asserturo@hotmail.com   A
    -| Camilla      555-2912     camilla.infusarum@skynet.be     R
    -| Fabius       555-1234     fabius.undevicesimus@ucb.edu    F
    -| Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
    -| Jean-Paul    555-2127     jeanpaul.campanorum@nyu.edu     R
    -| Jan  21  36  64 620
    -| Apr  21  70  74 514
    

    请注意,mail-list中以 Jean-Paul开头的行是如何打印两次的,每个规则一次。(开始时是匹配模式21,然后是匹配模式12

一个更复杂的例子

  • 现在,我们已经掌握了一些简单的任务,让我们看一下典型的awk程序可以做什么。 本示例说明了如何使用awk汇总,选择和重新排列另一个实用程序的输出。 它使用的功能尚未涵盖,因此,如果您不了解所有详细信息,请不要担心:

    ls -l | awk '$6 == "Nov" { sum += $5 }
            END { print sum }'
    

    此命令显示当前目录中所有文件的最后修改于11月(每年)的总字节数。 此示例的ls -l部分是系统命令,可提供目录中文件的列表,包括每个文件的大小和文件的最后修改日期。 其输出如下所示:

    -rw-r--r--  1 arnold   user   1933 Nov  7 13:05 Makefile
    -rw-r--r--  1 arnold   user  10809 Nov  7 13:03 awk.h
    -rw-r--r--  1 arnold   user    983 Apr 13 12:14 awk.tab.h
    -rw-r--r--  1 arnold   user  31869 Jun 15 12:20 awkgram.y
    -rw-r--r--  1 arnold   user  22414 Nov  7 13:03 awk1.c
    -rw-r--r--  1 arnold   user  37455 Nov  7 13:03 awk2.c
    -rw-r--r--  1 arnold   user  27511 Dec  9 13:07 awk3.c
    -rw-r--r--  1 arnold   user   7989 Nov  7 13:03 awk4.c
    

    第一个字段包含读写权限,第二个字段包含文件的链接数,第三个字段标识文件的所有者。 第四个字段标识文件的组。 第五个字段包含文件的大小(以字节为单位)。 第六,第七和第八字段分别包含文件的最后修改日期,月份,日期和时间。 最后,第九个字段包含文件名。

    在我们的awk程序中,$ 6 ==“Nov”是一个表达式,用于测试ls -l的输出的第六个字段是否与字符串'Nov'相匹配。 每当一行的第六个字段中包含字符串'Nov'时,awk都会执行操作'sum + = $5'。 这会将第五个字段(文件的大小)添加到变量sum中。 结果,当awk完成读取所有输入行时,sum是其行与模式匹配的文件大小的总和。 (这是有效的,因为awk变量会自动初始化为零。)

    处理完ls的最后一行输出后,将执行END规则并打印sum的值。 在此示例中,sum的值为80600

    这些更高级的awk技术将在后面的部分中介绍(请参阅Action一节)。 在继续进行更高级的awk编程之前,您必须知道awk如何解释您的输入并显示您的输出。 通过操作字段并使用打印语句,您可以生成一些非常有用且外观精美的报告。

awk语句与行

  • 通常,awk程序中的每一行都是单独的语句或单独的规则,如下所示:

    awk '/12/  { print $0 }
    /21/  { print $0 }' mail-list inventory-shipped
    

    但是,gawk会忽略以下任何符号和关键字之后的换行符:

    ,    {    ?    :    ||    &&    do    else
    

    在任何其他位置的换行符都被视为语句的结尾。

    如果您想在换行符将其终止的位置将单个语句分成两行,则可以通过在第一行以反斜杠字符(\)结束来继续执行该语句。 反斜杠必须是行上的最后一个字符,才能被识别为连续字符。 语句中的任何位置都可以使用反斜杠,后跟换行符,即使在字符串或正则表达式中间也是如此。 例如:

    awk '/This regular expression is too long, so continue it\
    on the next line/ { print $1 }'
    

    在示例程序中,我们通常没有使用反斜杠继续。 gawk对行的长度没有限制,因此从不严格要求反斜杠连续; 它只是使程序更具可读性。 出于同样的原因,并且为了清楚起见,我们在整个Web页面上显示的程序中都保留了大多数语句。

    awk程序位于单独的源文件中而不是从命令行输入时,反斜杠连续最有用。 您还应该注意,许多awk实现都更具体地说明了在何处可以使用反斜杠连续。 例如,它们可能不允许您使用反斜杠分割连续字符串常量。 因此,为了最大程度地实现awk程序的可移植性,最好不要在正则表达式或字符串中间拆分行。

    注意:反斜杠继续不能如C Shell中所述工作。 如果您使用的是POSIX-compliant shell,例如Unix Bourne shellBash,则它适用于文件中的awk程序和单发程序。 但是C Shell的行为有所不同! 在那里,您必须连续使用两个反斜杠,然后再使用换行符。 还要注意,使用C Shell时,awk程序中的每个换行符都必须以反斜杠转义。 为了显示:

    % awk 'BEGIN { \
    ?   print \\
    ?       "hello, world" \
    ? }'
    -| hello, world
    

    在这里,'%''?'C shell的主要和辅助提示,类似于standard shell'$''>'

    将前面的示例与如何使用POSIX-compliant shell进行比较:

    $ awk 'BEGIN {
    >   print \
    >       "hello, world"
    > }'
    -| hello, world
    

    awk是一种面向行的语言。 每个规则的动作必须与模式在同一行开始。 要在单独的行上包含模式和操作,必须使用反斜杠连续。 没有其他选择。

    要记住的另一件事是反斜杠继续和注释不会混合。 一旦awk看到开始注释的'#',它将忽略该行其余部分的所有内容。 例如:

    $ gawk 'BEGIN { print "dont panic" # a friendly \
    >                                    BEGIN rule
    > }'
    error→ gawk: cmd. line:2:                BEGIN rule
    error→ gawk: cmd. line:2:                ^ syntax error
    

    在这种情况下,反斜杠似乎会将注释继续到下一行。 但是,反斜杠和换行符的组合从未被注意到,因为它被隐藏在注释中。 因此,BEGIN被标记为语法错误。

    当一条规则中的awk语句很短时,您可能需要在一行中放置多个以上的语句。 这是通过用分号(;)分隔语句来完成的。 这也适用于规则本身。 因此,本节开始处显示的程序也可以这样编写:

    /12/ { print $0 } ; /21/ { print $0 }
    

    注意:要求同一行上的规则必须用分号分隔的要求不是原始的awk语言; 添加它是为了与操作中的语句处理保持一致。

第一章总结:

  1. awk中的程序由模式-动作对组成。
  2. 没有模式的动作始终运行。 一个模式的默认动作(也即没有指定动作的情况下)是'{print $ 0}'
  3. 使用 ‘awk 'program' files’ 或者 ‘awk -f program-file files’ 来运行awk。
  4. 您可以使用特殊的'#!'标题行来创建可直接执行的awk程序。
  5. awk程序中的注释以'#'开头,并持续到同一行的末尾。
  6. 在作为较大的Shell脚本(或 MS-Windows batch file)的一部分编写awk程序时,请注意引用问题。
  7. 您可以使用反斜杠继续来继续源代码行。 在逗号,大括号,问号,冒号,'||''&&''do'else操作之后,行会自动继续。

第二章总结:

  1. gawk从左到右解析命令行上的参数,以确定应将其视为选项还是非选项参数。

  2. gawk可以识别几个控制其操作的选项,如Command-Line Options中所述。 所有选项均以'-'开头。

  3. 任何不能识别为选项的参数都将被视为非选项参数,即使该参数以'-'开头。

    • 但是,当一个选项本身需要一个参数,并且该选项在命令行上与该参数至少间隔一个空格时,该空格将被忽略,并且该参数被视为与该选项相关。 因此,在调用'gawk -F x'时,'x'被视为属于-F选项,而不是单独的非选项参数。
  4. 一旦gawk找到了非选项参数,它就会停止寻找选项。 因此,所有后面的参数也都是非选项参数,即使它们类似于公认的选项。

  5. 如果不存在-e-f选项,则gawk希望程序文本位于第一个非选项参数中。

  6. 除第一个非选项参数中提供的程序文本外,所有非选项参数都按照使用ARGCARGV中的说明放置在ARGV中,并按照其他命令行参数中的说明进行处理。 调整ARGCARGV会影响awk处理输入的方式。

  7. 所有awk版本的三个标准选项是-f-F-vgawk提供了这些以及许多其他选项,以及相应的GNU风格的长选项。

  8. 非选项命令行参数通常被视为文件名,除非它们的格式为var = value,在这种情况下,它们将被视为在处理输入时在该位置执行的变量赋值。

  9. 您可以使用一个减号('-')来指代命令行上的标准输入。 gawk还允许您使用特殊文件名/dev/stdin

  10. gawk注意许多环境变量。 AWKPATHAWKLIBPATHPOSIXLY_CORRECT是最重要的。

  11. gawk的退出状态会将信息传达给调用它的程序。 在awk程序中使用exit语句设置退出状态。

  12. gawk允许您使用 @include语句或-i-f命令行选项将其他awk源文件包含到程序中。

  13. gawk允许您使用@load语句或-l选项加载用C或C ++编写的其他函数。 (此高级功能将在后面的“编写gawk的扩展”中进行介绍。)

这部分就先到这里啦!另外,正则表达式部分还需要详看,就记在下一篇把!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值