跳转到内容

AWK

25% developed
来自维基教科书,开放的书籍,为开放的世界
(重定向自 Awk)

此参考文档针对的是具备一定 UNIX 使用经验的用户,他们刚遇到一个问题,并且被建议使用 awk 来解决它。有关 awk 的更多信息,请参阅 Awk Primer.

以下是 awk 的主要版本

  • awk 或 Bell Labs awk
  • nawk 或 new awk
  • gawk (GNU awk)
  • mawk

nawk 和 gawk 都可以运行 awk 程序,无需修改。

获取 AWK:如果您使用的是 Linux 或 macOS,那么您已经拥有 AWK。对于 MS Windows,GNU awk 的版本可从 ezwinportsGnuWin32 项目Cygwin 获取。

Awk 从文件或标准输入读取数据,并将输出到标准输出。通常您需要将其重定向到文件,但在这些示例中没有这样做,只是为了节省空间。awk 不适用于非文本文件,例如可执行文件和 FrameMaker 文件。如果您需要编辑这些文件,请使用二进制编辑器,例如 emacs 中的 hexl-mode。

学习 awk 时的困难之一是如何让您的程序通过 shell 的解析器。正确的方法是在程序周围使用单引号,如下所示

>awk '{print $0}' filename

单引号可以保护几乎所有内容免受 shell 的影响。在 csh 或 tcsh 中,您仍然需要小心感叹号,但除此之外,您就很安全了。

学习 awk 时的另一个困难之处在于它提供的错误信息。

awk '{print $0,}' filename
awk: syntax error near line 1
awk: illegal statement near line 1

gawk 通常会提供更好的错误信息。至少它会告诉您错误发生在代码的哪一行。

gawk '{print $0,}' filename
gawk: cmd. line:1: {print $0,}
gawk: cmd. line:1:           ^ parse error

因此,如果您在使用 awk 语法时遇到问题,可以先尝试使用 gawk。

一些基础知识

[编辑 | 编辑源代码]
  • Awk 识别“文件”、“记录”和“字段”的概念。
  • 文件由记录组成,默认情况下记录就是文件中的每一行。一行就成为一条记录。
  • Awk 每次只操作一条记录。
  • 记录由字段组成,默认情况下字段由任意数量的空格或制表符分隔。
  • 第 1 个字段使用 $1 访问,第 2 个字段使用 $2 访问,以此类推。$0 指的是整个记录。

一些示例

[编辑 | 编辑源代码]

学习 awk 的最快方法之一就是看一些示例程序。上面的程序将打印整个文件,就像 cat(1) 一样。以下是其他一些程序,以及它们的作用的简要描述。

>awk '{print $2,$1}' filename

将打印第二个字段,然后是第一个字段。所有其他字段都会被忽略。

>awk '{print $1,$2,sin($3/$2)}' filename

将打印第一个和第二个字段,然后打印第三个字段除以第二个字段的正弦值。因此,第二个和第三个字段必须是数字。Awk 有其他内置的数学函数,例如正弦函数;请阅读手册页以了解这些函数。

"我仍然经常使用 awk '{print $1}'。"
PERL 的发明者,Larry Wall ([email protected])

如果您不想将程序应用于文件的每一行怎么办?例如,您可能只想处理第一个字段大于第二个字段的行。以下程序可以实现这一点

>awk '$1 > $2 {print $1,$2,$1-$2}' filename

花括号外的部分称为“模式”,花括号内的部分称为“操作”。比较运算符包括 C 中的运算符

== != < > <= >= ?:

如果没有指定模式,那么操作将应用于所有行。我们在上面的示例程序中使用了这一事实。如果没有指定操作,那么将打印整行。如果单独使用 "print",那么将打印整行。因此,以下几种方式是等效的

awk '$1 > $2'           filename
awk '$1 > $2{print}'    filename
awk '$1 > $2{print $0}' filename

一行中的各个字段也可以被视为字符串而不是数字。要将字段与字符串进行比较,可以使用以下方法

> awk '$1=="foo"{print $2}' filename

正则表达式

[编辑 | 编辑源代码]

如果您想要包含某个特定字符串的行怎么办?只需将一个 正则表达式(以 egrep(1) 的方式)放到模式中,如下所示

>awk '/foo.*bar/{print $1,$3}' filename

这将打印所有包含单词 "foo" 以及随后包含单词 "bar" 的行。如果您只想打印第二个字段中包含 "foo" 的行,可以使用 ~(“包含”)运算符

>awk '$2~/foo/{print $3,$1}' filename

如果您想要打印第二个字段中不包含 "foo" 的行,可以使用否定 ~ 运算符,即 !~

>awk '$2!~/foo/{print $3,$1}' filename

此运算符可以理解为“不包含”。

布尔值

[编辑 | 编辑源代码]

您可以使用 C 中的布尔运算符来创建复杂的模式,这些运算符包括 ! 表示“非”,&& 表示“与”,|| 表示“或”。可以使用括号进行分组。

开始和结束

[编辑 | 编辑源代码]

有三种特殊形式的模式不符合以上描述。一种是正则表达式的开始-结束对。例如,要打印包含 "foo" 和 "bar" 的行(包括这些行本身),可以使用以下代码

>awk '/foo/,/bar/' filename

开始和结束

[编辑 | 编辑源代码]

另外两种特殊形式与此类似;它们是 BEGIN 和 END 模式。与 BEGIN 模式关联的任何操作都将在任何逐行处理之前发生。与 END 模式关联的操作将在所有行处理完毕之后发生。

但是,如何在一个 awk 程序中添加多个模式-操作对呢?您可以选择几种方法。其中一种是将它们直接组合在一起,如下所示

 > awk 'BEGIN{print"fee"} $1=="foo"{print"fi"}
        END{print"fo fum"}' filename

另一种选择是将程序写入文件,如下所示

BEGIN{print"fee"}
$1=="foo"{print"fi"}
END{print"fo fum"}

假设该文件名为 giant.awk。现在,使用 awk 的 "-f" 标志运行它

> awk -f giant.awk filename

第三种选择是创建一个自己调用 awk 的文件。以下形式可以实现

#!/usr/bin/awk -f
BEGIN{print"fee"}
$1=="foo"{print"fi"}
END{print"fo fum"} 

如果我们将此文件命名为 giant2.awk,可以通过以下方式运行它:首先授予其执行权限,

> chmod u+x giant2.awk

然后直接调用它

> ./giant2.awk filename

awk 有变量,这些变量可以是实数或字符串。例如,以下代码打印第五列的运行总和

> awk '{print x+=$5,$0 }' filename

这在查看 "ls -l" 的文件大小时很有用。它在平衡支票簿时也很有用,如果支票金额保存在一列中。

awk 变量在第一次使用时会被初始化为零或空字符串。当然,哪个值取决于使用方式。

变量也可以用于保存中间值。此示例还介绍了使用分号分隔语句

 > awk '{d=($2-($1-4));s=($2+$1);print d/sqrt(s),d*d/s }' filename

请注意,最后的语句,在本例中为“print”,不需要分号。不过,加上它也不会造成任何伤害。

  • 整数变量可以用来引用字段。如果一个字段包含有关哪个其他字段重要的信息,此脚本将仅打印重要字段。
 > awk '{imp=$1; print $imp }' filename
  • 特殊变量 NF 会告诉您此记录中有多少个字段。此脚本将打印每个记录的第一个和最后一个字段,无论有多少个字段。
 > awk '{print $1, $NF}' filename
  • 特殊变量 NR 会告诉您这是第几条记录。每次读取新记录时,它都会递增。这提供了一种为文件添加行号的简单方法。
 > awk '{print NR, $0}' filename

当然,还有许多其他方法可以使用各种 UNIX 实用程序在文件上添加行号。这留作读者的练习。

  • 特殊变量 FS(字段分隔符)决定 awk 将如何将每个记录拆分为字段。此变量可以在命令行上设置。例如,/etc/passwd 的字段以冒号分隔。
 > awk -F: '{print $1,$3 }' /etc/passwd
此变量实际上可以设置为任何正则表达式,类似于 egrep(1)。

各个字段也是变量,您可以为它们赋值。如果要从每行中删除第 10 个字段,您可以通过使用 for 循环打印第 1 到 9 个字段,然后从第 11 个字段开始(参见下文)来实现。但是,这样做会非常简单。

 > awk '{$10=""; print }' filename

在许多方面,awk 类似于 C。存在“for”、“while”、“do-while”和“if”结构。语句可以用花括号分组。此脚本将打印每个记录的每个字段,每个字段占一行。

 > awk '{for(i=1;i<=NF;i++) print $i }' filename

如果您想生成比“print”语句提供的格式更漂亮的格式,您可以像在 C 中一样使用“printf”。这是一个将第一个字段视为字符串,然后进行一些数字处理的示例。

 > awk '{printf("%s %03d %02d %.15g\n",$1,$2,$3,$3/$2); }' filename

使用 printf 时,您需要显式换行符。

我们可以使用“printf”在不换行的情况下打印内容,这对于按反序打印记录字段,每行一个记录很有用。

 > awk '{for(i=NF;i > 0;i--) printf("%s",$i); printf("\n"); }' filename

关联数组

[edit | edit source]

awk 有关联数组,由字符串索引。它没有 C 语言中数组的直接类似物。字符串索引的关联数组本身很有用,但将它们用作普通数组很麻烦。

例如,我们可以统计文档中单词的出现频率(忽略打印它们的令人讨厌的部分)。

> awk '{for(i=1;i <=NF;i++) freq[$i]++ }' filename

该数组将为文件中出现的每个单词存储一个整数值。不幸的是,这将把“foo”、“Foo”和“foo,”视为不同的单词。好吧。我们如何打印这些频率?awk 有一个特殊的“for”结构,它遍历数组中的值。此脚本比大多数命令行长,因此它将表示为可执行脚本。

#!/usr/bin/awk -f
{for(i=1;i <=NF;i++) freq[$i]++ }
END{for(word in freq) print word, freq[word]  }

这个遍历数组的循环似乎没有特定的顺序。因此,此类程序的输出通常需要通过 sort(1) 进行管道传输才能变得有用。

多维数组以一种奇怪的方式实现。给定的索引将连接在一起(使用特殊分隔符)以获得一个字符串,并将其用作索引。此程序将打印单词对频率。

#!/usr/bin/awk -f
{for(i=1;i < NF;i++) freq[$i,$(i+1)]++ }
END{for(words in freq) print words, freq[words]  }

不幸的是,这将打印出分隔符,默认情况下它不是常用字符。您可以通过使用 nawk 或 gawk 为变量 SUBSEP 赋值一个逻辑值(例如空格)来更改此设置(在普通的 awk 中不允许这样做)。

#!/usr/bin/awk -f
BEGIN{SUBSEP=""}
{for(i=1;i < NF;i++) freq[$i,$(i+1)]++}
END{for(words in freq) print words, freq[words] }

不幸的是,这不能让您单独引用索引。这个技巧是使用“split”函数,它将字符串分解为数组。

#!/usr/bin/awk -f
BEGIN{SUBSEP="" }
{for(i=1;i < NF;i++) freq[$i,$(i+1)]++}
END{ for(words in freq)
     {
        split(words,word,SUBSEP); 
        print word[1], freq[words],word[2];
     } 
   }

链接

排序

[edit | edit source]

普通的 awk 没有内置函数来排序数组。但是,gawk 有asort(按值排序)和asorti(按索引排序,也称为键)函数。asort 会丢失原始索引,用 1 到 length 索引代替。

链接

来自文件的代码

[edit | edit source]

当您在文件中使用 awk 脚本时,可以将您的程序分解为多行,使其更容易阅读。注释以与 sh 编程相同的方式开始,使用 #。

#!/usr/bin/awk -f
# this program prints the frequencies of word pairs
BEGIN{SUBSEP=""} # set the index separator 
                 # to a nice character
{for(i=1;i < NF;i++) freq[$i,$(i+1)]++}
END{ for(words in freq)
     {
# just to show we can put a comment in here.
       split(words,word,SUBSEP); # or here
       print word[1], freq[words],word[2];
     } 
}		

您可以使用 awk 创建文本,以及处理现有文本。它对于快速生成函数值的表格很有用,而无需编译 C 程序的麻烦。例如,它可以显示 sin(x)/x 随着 x 接近零而接近 1。

> awk '{x=1.0/NR; print x,sin(x)/x;}'

每次读取新行时都会打印一个新值。因此,您可以一直按回车键,直到获得所有需要的值。或者,如果您需要固定数量的值,可以这样做。

> awk 'BEGIN{for(i=1;i <=30;i++){x=1.0/i;print x,sin(x)/x;}}' /dev/null

其中 30 是固定数量的值。

标点符号

[edit | edit source]
  • {} : 用于围绕操作,以及在操作中对语句进行分组。
  • $ : 表示一个字段。$1 是第一个字段,$0 是整个记录。
  • ~ : “包含”运算符。“foobar”~"foo" 为真。仅适用于字符串。
  • !~ : “不包含”运算符。仅适用于字符串。
  • == : 等于运算符。适用于数字或字符串。
  • < > <= >= != : 不等运算符。适用于数字或字符串。
  • # : 注释开始字符。
  • , : 在“print”或“printf”语句中分隔内容。
  • ; : 分隔语句。
  • // : 用于围绕正则表达式。
  • && : 布尔与。
  • || : 布尔或。
  • ! : 布尔非。
  • () : 用于对布尔表达式进行分组,向函数传递参数,以及在“for”、“while”等条件周围。

代码生成示例

[edit | edit source]

Awk 可用于生成不想手动输入的 C 代码。例如,此脚本将生成显式的 3x3 矩阵乘法例程。

gawk 'BEGIN{
        for(i=0;i<3;i++)
         for(j=0;j<3;j++){
           printf("d[%d][%d]=",i,j);
           for(k=0;k<3;k++){
             printf("l[%d][%d]*r[%d][%d]%s",
                    i,k,k,j,(k<2)?"+":";\n");
           }
         }
     }'

大型示例

[edit | edit source]

现在来看看一个大型示例。

# This awk program collects statistics on two 
# "random variables" and the relationships 
# between them. It looks only at fields 1 and 
# 2 by default Define the variables F and G 
# on the command line to force it to look at
# different fields.  For example: 
# awk -f stat_2o1.awk F=2 G=3 stuff.dat \
# F=3 G=5 otherstuff.dat
# or, from standard input: 
# awk -f stat_2o1.awk F=1 G=3
# It ignores blank lines, lines where either 
# one of the requested fields is empty, and 
# lines whose first field contains a number 
# sign. It requires only one pass through the
# data. This script works with vanilla awk 
# under SunOS 4.1.3.
BEGIN{
  F=1;
  G=2;
}
length($F) > 0 && \
length($G) > 0 && \
$1 !~/^#/ {
  sx1+= $F; sx2 += $F*$F;
  sy1+= $G; sy2 += $G*$G;
  sxy1+= $F*$G;
  if( N==0 ) xmax = xmin = $F;
  if( xmin > $F ) xmin=$F;
  if( xmax < $F ) xmax=$F;
  if( N==0 ) ymax = ymin = $G;
  if( ymin > $G ) ymin=$G;
  if( ymax < $G ) ymax=$G;
  N++;
}
 
END {
  printf("%d # N\n"   ,N   );
  if (N <= 1) 
    {
    printf("What's the point?\n");
    exit 1;
    }
  printf("%g # xmin\n",xmin);
  printf("%g # xmax\n",xmax);
  printf("%g # xmean\n",xmean=sx1/N);
  xSigma = sx2 - 2 * xmean * sx1+ N*xmean*xmean;
  printf("%g # xvar\n"         ,xvar =xSigma/  N  );
  printf("%g # xvar unbiased\n",xvaru=xSigma/(N-1));
  printf("%g # xstddev\n"         ,sqrt(xvar ));
  printf("%g # xstddev unbiased\n",sqrt(xvaru));
  
  printf("%g # ymin\n",ymin);
  printf("%g # ymax\n",ymax);
  printf("%g # ymean\n",ymean=sy1/N);
  ySigma = sy2 - 2 * ymean * sy1+ N*ymean*ymean;
  printf("%g # yvar\n"         ,yvar =ySigma/  N  );
  printf("%g # yvar unbiased\n",yvaru=ySigma/(N-1));
  printf("%g # ystddev\n"         ,sqrt(yvar ));
  printf("%g # ystddev unbiased\n",sqrt(yvaru));
  if ( xSigma * ySigma <= 0 )
    r=0;
  else 
    r=(sxy1 - xmean*sy1- ymean * sx1+ N * xmean * ymean)
      /sqrt(xSigma * ySigma);
  printf("%g # correlation coefficient\n", r);
  if( r > 1 || r < -1 )
    printf("SERIOUS ERROR! CORRELATION COEFFICIENT");
    printf(" OUTSIDE RANGE -1..1\n");

  if( 1-r*r != 0 )
    printf("%g # Student's T (use with N-2 degfreed)\n&", \
      t=r*sqrt((N-2)/(1-r*r)) );
  else
    printf("0 # Correlation is perfect,");
    printf(" Student's T is plus infinity\n");
  b = (sxy1 - ymean * sx1)/(sx2 - xmean * sx1);
  a = ymean - b * xmean;
  ss=sy2 - 2*a*sy1- 2*b*sxy1 + N*a*a + 2*a*b*sx1+ b*b*sx2 ;
  ss/= N-2;
  printf("%g # a = y-intercept\n", a);
  printf("%g # b = slope\n"      , b); 
  printf("%g # s^2 = unbiased estimator for sigsq\n",ss);
  printf("%g + %g * x # equation ready for cut-and-paste\n",a,b);
  ra = sqrt(ss * sx2 / (N * xSigma));
  rb = sqrt(ss       / (    xSigma));
  printf("%g # radius of confidence interval ");
  printf("for a, multiply by t\n",ra);
  printf("%g # radius of confidence interval ");
  printf("for b, multiply by t\n",rb);
}

此文档最初由 Andrew M. Ross 编写。它可以在 这里找到,并且由 Harvey Mudd College 计算机科学系根据 GFDL 发布。

选项

[edit | edit source]

awk 的命令行选项,也称为开关。

  • -F field-separator: 使用字段分隔符正则表达式来分隔字段。
  • -f source-file
  • -v var=val: 将变量设置为该值。由 POSIX 定义;在原始 awk 中不存在。

GNU awk 的命令行选项,也称为开关,超出了基本的 awk。

  • -W gawk-opt
  • ...
  • --posix
  • ...

链接

数学

[edit | edit source]

支持常用的运算符 +、-、*、/、 %、^;gawk 支持 **,但 POSIX awk 不支持。内置数学函数包括 exp、log、sqrt、sin、cos、atan2、rand、srand 和 int。

数字文字为十进制;它们可以在 C 语言风格中使用十六进制和八进制,在 gawk 中使用 GNU 扩展。

链接

用户定义函数

[edit | edit source]

用户定义函数可以按以下方式定义。

  • function plus(x,y) { return x+y }

一些 awk 实现(包括 gawk)允许使用“func”代替“function”,但这不符合 POSIX 标准。

支持递归。

  • awk 'function fact(x) { if (x > 1) { return x*fact(x-1) } else return 1} BEGIN{print fact(4)}'

链接

位操作

[编辑 | 编辑源代码]

传统的 awk 没有位运算符来提供位操作。然而,gawk 内置了位操作函数,包括 and()、or()、xor()、compl()、lshift() 和 rshift()。

链接

包含库

[编辑 | 编辑源代码]

传统的 awk 无法在 awk 程序中包含或导入函数库;最接近的方法是多次使用 -f 选项。相反,gawk 提供了这种可能性作为 GNU 扩展,使用 @include 关键字。

只要包含库文件的目录在 AWKPATH 环境变量中,就不需要指定库文件的完整路径。设置 AWKPATH 可防止 awk 将当前目录视为路径的一部分,除非 AWKPATH 包含句点 (.) 来表示当前目录。AWKPATH 的项目分隔符是冒号 (:),或 Windows 上的分号 (;)。

也可以通过 gawk 的 -i 选项加载 awk 函数库。因此,如果您有文件 lib.awk,该文件所在目录的路径在 AWKPATH 中,并且该文件定义了 abs 函数,您可以像这样调用 gawk

  • awk -ilib "BEGIN {print abs(-4)}"

您无法使用 -f 选项执行此操作;您必须将主程序存储在单独的文件中,然后在同一命令行上两次使用 -f 选项,第一次加载库,第二次加载主程序。

可以在 GitHub 上的 Many AWK 项目中找到许可自由的 awk 库。

链接

单行示例

[编辑 | 编辑源代码]

awk 使用的单行示例

  • echo abcd |awk '/b.*d/'
    • 输出与正则表达式匹配的行,类似 grep 命令。
  • echo abcd |awk '/b.*d/ {print $0}'
    • 与上面相同,但使用显式打印语句。$0 代表整行。
  • echo ab   cd |awk '/b.*d/ {print $2}'
    • 对于与正则表达式匹配的行,输出第二字段。默认情况下使用空格序列作为字段分隔符。因此,输出“cd”。
  • echo abcd,e |awk -F, '/b.*d/ {print $2}'
    • 对于与正则表达式匹配的行,输出第二字段,由于 -F 选项,使用逗号作为字段分隔符。因此,输出“e”。
  • echo abcd,e |awk '{print toupper($0)}'
    • 输出所有行的大写字母。对于小写字母,使用“tolower”。
  • echo a b c d | awk '{print $NF, $(NF-1)}'
    • 输出最后一个字段和倒数第二个字段;NF 是字段数量。
  • echo ab cd | awk 'NF>=2'
    • 输出字段数量为 2 或更大的行。
  • echo ab cd | awk '{print NF}'
    • 对于每一行,输出该行中的字段数量。
  • echo ab cd | awk 'length($2) > 1'
    • 输出第二字段长度大于 1 的所有行。
  • echo ab cd | awk '$2 ~ /cd/'
    • 输出第二字段与正则表达式匹配的所有行。
  • echo ab cd | awk '$1 ~ /ab/ && $2 ~ /cd/'
    • 与上面类似,但使用两个由“&&”连接的子条件。支持 C 编程语言中已知的其他一些逻辑运算符。
  • cat file.txt | awk 'NR >= 100 && NR <= 500'
    • 输出行号在指定范围内的行(记录)。因此,充当行号过滤器。
  • cat file.txt | awk 'NR == 1 || /reg.*pattern/'
    • 输出第一行和与正则表达式匹配的行。
  • echo abcd | awk '{gsub(/ab/,"ef");print}'
    • 替换,也称为替换,类似于 sed 命令;gsub 中的“g”代表全局。
  • awk 'BEGIN{for(i=1;i<6;i++) print sqrt(i)}'
    • 输出 1、…、5 中整数的平方根。使用 BEGIN{} 可确保代码无论是否将任何输入行馈送到 awk 都能执行。for 循环使用熟悉的 C 语言语法,sqrt 是多个可用数学函数之一。
  • awk 'BEGIN{printf "%i %.2f\n", 1, (2+3)/7}'
    • 支持来自 C 语言的熟悉函数 printf,作为不需要在参数周围使用括号的语句。
  • awk 'BEGIN{for(i=1;i<9;i++) a[i]=i^2; for(i in a) print i, a[i]}'
    • 借助 awk 关联数组(也称为映射或字典),输出几个整数及其平方。输出的顺序是不确定的,这在关联数组中很常见。awk 没有其他编程语言中已知的数组和列表的直接对应物。
  • cat file.txt | awk '{sum+=$1} END{print sum}'
    • 使用 END 关键字输出第一字段(列)中值的总和。
  • printf 1,2,3\\n4,5,6 | awk -F, '{s=0;for(i=1; i<=NF; i++) {s+=$i} print s}'
    • 对于逗号分隔文件的每一行,输出该行中字段(列)的总和。因此,遍历字段。
  • echo 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 | awk -F, -vn=7 '{for(i=1;i<=NF; i++) {s+=i>n?$i-$(i-n):$i; if(i>=n){printf "%.0f, ", s/n}else{printf ", "}}}'
    • 输出逗号分隔的输入逗号分隔序列的 7 值简单移动平均值。
  • awk 'BEGIN{system("dir")}'
    • 运行外部命令 dir;在沙箱模式下禁用。
  • awk 'function abs(x) {return x < 0 ? -x : x} BEGIN{print abs(-4)}'
    • 定义并使用绝对值函数。显示了来自 C 语言的三元运算符的使用。

链接

在线尝试

[编辑 | 编辑源代码]

您可以在 http://awk.js.org/ 上在线尝试 awk。关键词:REPL 在线。

局限性

[编辑 | 编辑源代码]

与其他脚本语言相比,AWK 的局限性包括以下内容

  • 没有其他编程语言中已知的数组和列表的直接对应物,只有关联数组。
  • 没有嵌套数组:关联数组的值不能是数组。
  • 没有真正的多维数组:多个索引存储为通过分隔符连接索引而形成的单个索引。
  • 在普通 awk 中没有数组的排序函数,只有在 gawk 中有。
  • 在普通 awk 中没有位运算符;gawk 有位操作函数,包括 and()、or()、compl() 等。
  • 在传统的 awk 中不支持包含要由 awk 脚本重用的函数的库或模块;但是,gawk 支持用于该目的的 @include 关键字。
  • 不支持 GUI 编程。

链接

源代码

[编辑 | 编辑源代码]

各种版本的 awk 的源代码

另请参见

[编辑 | 编辑源代码]
  • O'Reilly 的 sed & awk 袖珍参考
  • UNIX 概览
  • UNIX 权力工具
[编辑 | 编辑源代码]
华夏公益教科书