跳转到内容

Awk 入门/Nawk

来自维基教科书,开放世界中的开放书籍

Awk 的最初版本是在 1977 年开发的。它针对快速编写“单行程序”或简短、快速、简陋的程序进行了优化。然而,一些用户非常喜欢 Awk,以至于他们将它用于更复杂的任务。引用语言作者的话:“当我们遇到一个不适合在一页上显示的程序时,我们感到震惊和惊讶。”一些用户将 Awk 视为他们主要编程工具,事实上许多人学习编程就是使用 Awk。

在作者克服了最初的震惊后,他们决定接受这一事实,并增强 Awk,使其成为更好的通用编程工具。新版本的 Awk 于 1985 年发布。新版本通常(如果不总是)被称为 Nawk(“新 Awk”),以区别于旧版本。


  • Nawk 包含了一些重大改进。最重要的改进是用户可以定义自己的函数。例如,以下 Nawk 程序实现了“signum”函数
   {for (field=1; field<=NF; ++field) {print signum($field)}};

    function signum(n) {
       if (n<0)
       return -1
       else if (n==0) return 0
       else
           return 1}

函数声明可以放置在程序中的任何地方,只要匹配-操作子句可以放置的地方都可以。所有参数都是函数的局部变量。局部变量可以在函数内部定义。

  • 第二个改进是一个新函数“getline”,它允许从除了在调用时指定的命令行中的文件以外的文件中输入(以及从管道输入)。“Getline”可以以多种方式使用
   getline                   Loads $0 from current input.
   getline myvar             Loads "myvar" from current input.
   getline myfile            Loads $0 from "myfile".
   getline myvar myfile      Loads "myvar" from "myfile".
   command | getline         Loads $0 from output of "command".
   command | getline myvar   Loads "myvar" from output of "command".

  • 一个相关的函数“close”允许关闭文件,以便再次从开头读取
   close("myfile")
  • 一个新函数“system”允许 Awk 程序调用系统命令
   system("rm myfile")

  • 命令行参数可以使用两个新的预定义变量 ARGC 和 ARGV 来解释,这是一种对 C 程序员来说立即熟悉的机制。ARGC(“参数计数”)给出命令行元素的数量,而 ARGV(“参数向量”)是一个数组,其条目分别存储元素。
  • 存在一个新的条件赋值表达式,称为“?:”,其用法如下
   status = (condition == "green")? "go" : "stop"

这转换为

   if (condition=="green") {status = "go"} else {status = "stop"}

这种结构也应该对 C 程序员来说很熟悉。

  • 有新的数学函数,例如三角函数和随机数函数
   sin(x)         Sine, with x in radians.
   cos(x)         Cosine, with x in radians.
   atan2(y,z)     Arctangent of y/x, in range -PI to PI.
   rand()         Random number, with 0 <= number < 1.
   srand()        Seed for random-number generator.

  • 有新的字符串函数,例如匹配函数和替换函数
    • match(<目标字符串>,<搜索字符串>)
      在目标字符串中搜索搜索字符串;如果未匹配,则返回 0,如果匹配,则返回搜索字符串的起始索引。还将内置变量 RSTART 设置为起始索引,并将内置变量 RLENGTH 设置为匹配字符串的长度。
    • sub(<正则表达式>,<替换字符串>)
      在 $0 中搜索正则表达式的第一个匹配项并替换替换字符串。该函数返回所做替换的数量,就像其他替换函数一样。
    • sub(<正则表达式>,<替换字符串>,<目标字符串>)
      在目标字符串中搜索正则表达式的第一个匹配项并替换替换字符串。
    • gsub(<正则表达式>,<替换字符串>)
      在 $0 中搜索正则表达式的所有匹配项并替换替换字符串。
    • sub(<正则表达式>,<替换字符串>,<目标字符串>)
      在目标字符串中搜索正则表达式的所有匹配项并替换替换字符串。


  • 存在一种处理多维数组的机制。例如,以下程序创建并打印一个矩阵,然后打印该矩阵的转置
   BEGIN {count = 1;
      for (row = 1; row <= 5; ++row) {
        for (col = 1; col <= 3; ++col) {
          printf("%4d",count);
          array[row,col] = count++; }
        printf("\n"); }
      printf("\n");

      for (col = 1; col <= 3; ++col) {
         for (row = 1; row <= 5; ++row) {
            printf("%4d",array[row,col]); }
         printf("\n"); }
      exit; }

这会产生

   1   2   3    4   5   6    7   8   9    10  11  12    13  14  15

   1   4   7  10  13    2   5   8  11  14    3   6   9  12  15

Nawk 还包含一个新的“delete”函数,它删除数组元素

   delete(array[count])
  • 字符可以表示为八进制代码。例如,“\033”可用于定义“转义”字符。


  • 一个新的内置变量 FNR 会跟踪当前文件的记录号,而不是 NR,NR 会跟踪当前输入行的记录号,而不管有多少文件贡献了该输入。它的行为与 NR 完全相同。
  • 虽然 Nawk 确实有一些有用的改进,但它们通常旨在支持复杂程序的开发。我的感觉是,对于除了最专注的 Awk 用户之外的所有用户来说,Nawk 都过于复杂,而且无论如何都需要一个单独的文档才能充分说明其功能。那些想要了解有关 Nawk 更多信息的人,可以阅读 Aho/Weinberger/Kernighan 撰写的《AWK 编程语言》。这本简短、简洁、详细的书籍概述了 Nawk 的功能,并提供了使用它的复杂示例。
华夏公益教科书