GAWK(1) 实用程序命令 GAWK(1)
gawk - 模式扫描和处理语言
gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
gawk [ POSIX or GNU style options ] [ -- ] program-text file ...
pgawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
pgawk [ POSIX or GNU style options ] [ -- ] program-text file ...
dgawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
Gawk是GNU项目对AWK编程语言的实现。它符合POSIX 1003.1标准中对语言的定义。这个版本反过来是基于Aho、Kernighan和Weinberger用AWK编程语言( The AWK Programming Language)描述的。Gawk提供了在当前UNIX awk的版本和一些特定于GNU的扩展中发现的附加功能。
命令行包含一些选项,包括gawk本身、AWK程序文本(如果不是通过 -f 或 --file选项提供的),以及 预定义的AWK变量ARGC 和 ARGV 中可用的值。
Pgawk是gawk的剖析版。它在所有方面和gawk都是一样的,只是程序运行得更慢,完成后它会在文件awkprof.out中自动生成一个执行配置文件。参见下面的--profile选项。
Dgawk是一个awk调试器。它不是直接运行程序,而是加载AWK源代码,然后提示调试命令。与gawk和pgawk不同,dgawk只处理带有-f选项的AWK程序源代码。调试器记录在GAWK: Effective AWK Programming。
摘录:
awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行各种分析处理。
awk有3个不同版本: awk、nawk和gawk,未作特别说明,一般指gawk,gawk 是 AWK 的 GNU 版本。
awk其名称得自于它的创始人 Alfred Aho 、Peter Weinberger 和 Brian Kernighan 姓氏的首个字母。实际上 AWK 的确拥有自己的语言: AWK 程序设计语言 , 三位创建者已将它正式定义为“样式扫描和处理语言”。它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
AWK工作流程可分为三个部分:
命令结构:
awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
工作流程图如下:
语法格式如下:
BEGIN {awk-commands}
开始块就是在程序启动的时候执行的代码部分,并且它在整个过程中只执行一次。
一般情况下,我们可以在开始块中初始化一些变量。
BEGIN 是 AWK 的关键字,因此它必须是大写的。
注意:开始块部分是可选的,你的程序可以没有开始块部分。
语法格式如下:
/pattern/ {awk-commands}
对于每一个输入的行都会执行一次主体部分的命令。
默认情况下,对于输入的每一行,AWK 都会执行命令。但是,我们可以将其限定在指定的模式中。
注意:在主体块部分没有关键字存在。
语法如下:
END {awk-commands}
结束块是在程序结束时执行的代码。 END 也是 AWK 的关键字,它也必须大写。 与开始块相似,结束块也是可选的。
Gawk选项可以是传统的POSIX-style的单字母选项,也可以是GNU-style的长选项。POSIX选项以单个“-”开头,而长选项以“--”开头。为特定于GNU的特性和POSIX强制的特性,提供了长选项。
特定于Gawk的选项通常以长选项的形式使用。长选项的参数要么用=符号与该选项连接,中间没有空格,要么在下一个命令行参数中提供它们。Long选项可以缩写,只要缩写保持惟一。
此外,每个长选项都有一个对应的短选项,因此该选项的功能可以从#!可执行脚本内使用。
Gawk接受以下选项。首先列出标准选项,然后是gawk扩展选项。
-f program-file
--file program-file
从文件program-file中读取AWK程序源代码,而不是从第一个命令行参数中读取。可以使用多个-f(或--file)选项
-F fs
--field-separator fs
使用fs作为输入字段分隔符(预定义变量FS的值)。
-v var=val
--assign var=val
在程序开始执行之前,将val值赋给变量var。这样的变量值可用于一个awk程序的BEGIN块。
-b
--characters-as-bytes
将所有输入数据视为单字节字符。换句话说,当试图将字符串处理为多字节字符时,不要注意语言环境信息。--posix选项覆盖了这个。
-c
--traditional
以兼容模式运行。在兼容模式下,gawk的行为与UNIX awk相同;不识别任何特定于GNU的扩展。有关更多信息,请参见下面的 GNU EXTENSIONS。
-C
--copyright
在标准输出上打印GNU版权信息消息的短版本并成功退出。
-d[file]
--dump-variables[=file]
打印全局变量及其类型和最终值的排序列表到file。如果没有提供file,gawk将在当前目录中使用名为awkvars.out的文件。 拥有所有全局变量的列表是在程序中查找排版错误的好方法。如果您有一个包含许多函数的大型程序,并且您希望确保您的函数不会无意中使用要作为本地变量的全局变量,则也可以使用此选项。(对于i、j等简单的变量名,这是一个特别容易犯的错误。)
-e program-text
--source program-text
使用program-text 作为AWK程序源代码。该选项允许将库函数(通过-f和-file选项使用)与在命令行中输入的源代码轻松地混合在一起。它主要用于shell脚本中使用的大中型AWK程序。
-E file
--exec file
与-f类似,但是,这是最后一个处理的选项。这应该使用于#!脚本,特别是用于CGI应用程序,以避免从URL在命令行上传递选项或源代码(!)。此选项禁用命令行变量赋值。
-g
--gen-pot
扫描和解析AWK程序,并在标准输出上生成一个GNU .pot (可移植对象模板)格式文件,其中包含程序中所有可本地化字符串的条目。程序本身不执行。有关.pot文件的更多信息,请参阅GNU gettext发行版。
-h
--help
-L [value]
--lint[=value]
提供关于可疑或不可移植到其他AWK实现的构造的警告。带有fata的可选参数,lint警告将成为致命错误。这可能是极端的,但它的使用肯定会鼓励开发更干净的AWK程序。如果可选参数为invalid,则只发出关于实际无效的内容的警告。(这还没有完全实现。)
-n
--non-decimal-data
识别输入数据中的八进制和十六进制值。谨慎使用此选项!
-N
--use-lc-numeric
这迫使gawk在解析输入数据时使用本地的小数点字符。虽然POSIX标准要求这种行为,并且gawk在--posix生效时也这样做,但是默认情况下遵循传统行为,并使用句点作为小数点,即使在句点不是小数点字符的地区也是如此。该选项覆盖默认行为,而不具有--posix选项的严格性。
-O
--optimize
对程序的内部表示形式启用优化。目前,这只包括简单的常量折叠。gawk维护者希望随着时间的推移添加额外的优化。
-p[prof_file]
--profile[=prof_file]
将分析数据发送到prof_file。默认值是awkprof.out。当运行gawk时,该配置文件只是程序的“漂亮打印”版本。当使用pgawk运行时,概要文件在左侧空白处包含程序中每个语句的执行计数,以及每个用户定义函数的函数调用计数。
-P
--posix
这将打开兼容模式,并附加以下限制:
1. 无法识别 \x 转义序列。
2. 当FS被设置为单个空格时,只有空格和制表符充当字段分隔符,而换行符则不可以。
3. ? 和 : 后面不能续行。
4. 关键字function的同义词func无法识别。
5. 运算符**和**=不能代替^和^=。
-r
--re-interval
在正则表达式匹配中启用区间表达式(interval expressions)(参见下面的 Regular Expressions)。在AWK语言中,间隔表达式传统上是不可用的。POSIX标准添加了它们,以使awk和egrep保持一致。默认情况下,它们是启用的,但是这个选项仍然与 --traditional一起使用。
-R
--command file
仅限Dgawk命令。从file中读取存储的调试器命令。
-S
-sandbox
以沙箱模式运行gawk,禁用system()函数,使用getline重定向输入,使用print和printf重定向输出,并加载动态扩展。命令执行(通过管道)也被禁用。这可以有效地阻止脚本访问本地资源(命令行中指定的文件除外)。
-t
--lint-old
提供关于 不能移植到Unix awk原始版本的构造 的警告。
-V
--version
在标准输出上打印gawk的这个特定副本的版本信息。这主要是为了了解您的系统上gawk的当前副本是否与自由软件基金会(Free Software Foundation)发布的任何内容相关,是最新的。这在报告bug时也很有用。(根据GNU编码标准,这些选项会导致立即成功退出。)
--
表示选项结束。这有助于允许AWK程序本身的进一步参数以“-”开头。这与大多数其他POSIX程序使用的参数解析约定保持一致。
在兼容模式下,任何其他选项都被标记为无效,但在其他情况下将被忽略。在正常操作中,只要提供了程序文本,就会将未知选项传递给ARGV数组中的AWK程序进行处理。这对于通过#!可执行解释器机制运行AWK程序特别有用。
AWK程序由一系列模式操作语句和可选函数定义组成。
@include "filename" pattern { action statements}
function name(parameter list) {statements}
Gawk首先从program-file(s)(如果指定的话)、从参数到--source或从命令行上的第一个非选项参数读取程序源代码。可以在命令行上多次使用-f和--source选项。Gawk读取程序文本时,就像将所有program-files和命令行源文本连接在一起一样。这对于构建AWK函数库非常有用,而不必将它们包含在使用它们的每个新的AWK程序中。它还提供了将库函数与命令行程序混合的能力。
此外,以@include开头的行可以用于将其他源文件包含到程序中,从而使库的使用更加容易。
环境变量AWKPATH指定了当查找使用-f选项命名的源文件时使用的搜索路径。如果这个变量不存在,默认路径是“.:/usr/local/share/awk”。(实际目录可能有所不同,这取决于gawk是如何构建和安装的。)如果给-f选项的文件名包含“/”字符,则不执行路径搜索。
Gawk按照以下顺序执行AWK程序。首先,执行通过-v选项指定的所有变量赋值。接下来,gawk将程序编译成内部形式。然后,gawk执行BEGIN块(如果有的话)中的代码,然后读取ARGV数组(直到ARGV[ARGC])中命名的每个文件。如果命令行上没有指定文件,gawk将读取标准输入。
如果命令行上的文件名具有var=val格式,则将其视为变量赋值。变量var将被赋值val。(此操作在运行任何BEGIN块之后发生。)命令行变量赋值对于动态地为AWK用于控制输入如何分解为字段和记录的变量赋值是最有用的。如果需要在单个数据文件上进行多次传递,它还可以用于控制状态。
如果ARGV的某个特定元素的值是空的(""),gawk就跳过它。
对于每个输入文件,如果存在一个BEGINFILE规则,gawk在处理文件内容之前执行相关代码。类似地,gawk在处理文件后执行与ENDFILE相关的代码。
对于输入中的每条记录,gawk测试它是否与AWK程序中的任何pattern匹配。对于此记录匹配的每个模式,执行关联的action。按照模式在程序中出现的顺序对它们进行测试。
最后,在所有输入都用完之后,gawk执行END块(如果有的话)中的代码。
根据POSIX,在awk命令行上命名的文件必须是文本文件。如果没有定义,则行为是“未定义的”。大多数版本的awk都将命令行上的目录视为致命错误。
AWK变量是动态的;当它们第一次被使用时就产生了。它们的值是浮点数或字符串,或者两者都是,这取决于如何使用它们。AWK也有一维数组;可以模拟多维数组。在程序运行时设置几个预定义的变量;这些变量将根据需要进行描述,并在下面进行总结。
通常,记录由换行符分隔。您可以通过为内置变量RS赋值来控制记录的分隔方式。如果RS是任何单个字符,那么该字符将分隔记录。否则,RS就是一个正则表达式。与此正则表达式匹配的输入中的文本分隔记录。然而,在兼容模式下,只使用其字符串值的第一个字符来分隔记录。如果RS设置为空字符串,那么记录之间用空行分隔。当RS设置为空字符串时,除了FS可能具有的任何值之外,换行符始终充当字段分隔符。
在读取每个输入记录时,gawk使用FS变量的值作为字段分隔符,将记录分割为字段。如果FS是单个字符,则字段由该字符分隔。如果FS是空字符串,那么每个单独的字符就成为一个单独的字段。否则,FS应该是一个完整的正则表达式。在FS是单个空格的特殊情况下,字段由空格和/或制表符和/或换行分隔。(但是请参阅下面POSIX兼容性一节)。注意:IGNORECASE的值(参见下面)还影响到当FS是正则表达式时字段如何分割,当RS是正则表达式时记录如何分割。
如果将FIELDWIDTHS变量设置为以空格分隔的数字列表,则每个字段的宽度都应该是固定的,gawk使用指定的宽度分割记录。忽略FS的值。为FS或FPAT分配新值会覆盖FIELDWIDTHS的使用。
类似地,如果将FPAT变量设置为表示正则表达式的字符串,则每个字段由匹配该正则表达式的文本组成。在本例中,正则表达式描述字段本身,而不是分隔字段的文本。为FS或FIELDWIDTHS分配新值会覆盖FPAT的使用。
输入记录中的每个字段可以由其位置$1、$2等引用。$0是整个记录。字段不需要常量引用:
n = 5
print $n
打印输入记录中的第五个字段。
变量NF被设置为输入记录中字段的总数。
对不存在字段的引用(即$NF之后的字段)会生成空字符串。但是,分配给一个不存在的字段(例如$NF+2= 5)会增加NF的值,创建以null字符串作为值的任何中间字段,并导致重新计算$0的值,字段之间用OFS的值分隔。对负数字段的引用会导致致命错误。递减NF会导致新值之后的字段值丢失,并重新计算$0的值,字段之间用OFS的值分隔。
为现有字段赋值会导致在引用$0时重新生成整个记录。类似地,将值赋给$0会导致重新切分记录,从而为字段创建新值。
Gawk的内置变量如下:
ARGC 命令行参数的数量(不包括gawk选项或程序源代码)。
ARGIND 正在处理的当前文件的ARGV中的索引。
ARGV 命令行参数数组。数组的索引从0到ARGC - 1。动态更改ARGV的内容可以控制用于数据的文件。
BINMODE 在非posix系统上,指定对所有文件I/O使用“二进制”模式。数值1、2或3分别指定输入文件、输出文件或所有文件应该使用二进制I/O。字符串值“r”或“w”分别指定输入文件和输出文件应该使用二进制I/O。字符串值“rw”或“wr”指定所有文件都应该使用二进制I/O。任何其他字符串值都被视为“rw”,但会生成一条警告消息。
CONVFMT 数字转换格式,默认是"%.6g" 。
ENVIRON 包含当前环境值的数组。数组以环境变量为索引,每个元素都是该变量的值(例如,environmenton ["HOME"]可能是/home/arnold)。更改此数组不会影响 通过重定向或system()函数生成的gawk程序所看到的环境。
ERRNO 如果系统错误发生在为getline执行重定向、读取getline或close()期间,则ERRNO将包含描述错误的字符串。该值受非英语地区翻译的限制。
FIELDWIDTHS 以空格分隔的字段宽度列表。设置好后,gawk将输入解析为固定宽度的字段,而不是使用FS变量的值作为字段分隔符。参见上面的Fields。
FILENAME 当前输入文件的名称。如果命令行上没有指定文件,FILENAME的值为“ ”。但是,文件名在BEGIN块中没有定义(除非由getline设置)。
FNR 当前输入文件中输入记录数。
FPAT 描述记录中字段内容的正则表达式。设置好后,gawk将输入解析到字段中,字段与正则表达式匹配,而不是使用FS变量的值作为字段分隔符。参见上面的FIelds。
FS 输入字段分隔符,默认是一个空格。参见上面的Fields。
IGNORECASE 控制所有正则表达式和字符串操作的大小写敏感性。如果IGNORECASE有一个非零值,则当执行正则表达式操作时,在规则中进行字符串比较和模式匹配,使用FS和FPAT进行字段拆分,使用RS进行记录分隔,使用~和!~匹配正则表达式,以及gensub()、gsub()、index()、match()、patsplit()、split()和sub()内置函数都忽略大小写。 注意:数组下标不受影响。但是,asort()和asorti()函数会受到影响。 因此,如果IGNORECASE不等于零,/aB/匹配所有字符串“aB”、“aB”、“aB”和“aB”。与所有AWK变量一样,IGNORECASE的初值为零,因此所有正则表达式和字符串操作通常区分大小写。
LINT 在AWK程序中提供--lint选项的动态控制。如果是真的,gawk会打印lint警告。当是假的时候,它不会。当指定字符串值"fatal"时,lint警告将变成致命错误,就像--lint=fatal一样。任何其他真值只打印警告。
NF 当前输入记录中的字段数。
NR 到目前为止所看到的输入记录的总数。
OFMT 数字的输出格式,默认是"%.6g"。
OFS 输出字段分隔符,默认是一个空格。
ORS 输出记录分隔符,默认是一个换行符。
PROCINFO 这个数组的元素提供了对正在运行的AWK程序的信息的访问。在某些系统上,数组中可能有元素,对于某些n,从“group1”到“groupn”,这是进程拥有的补充组的数量。使用in操作符测试这些元素。以下要素保证可用:
PROCINFO["egid"] getegid(2)系统调用的值。
PROCINFO["strftime"] strftime()默认的时间格式字符串。
PROCINFO["euid"] geteuid(2)系统调用的值。
PROCINFO["FS"] 如果用FS分割字段是有效的则为"FS";如果用FPAT分割字段是有效的则为"FPAT";如果用FIELDWIDTHS分割字段是有效的则为"FILEDWIDTHS";
PROCINFO["gid"] getgid(2)系统调用的值。
PROCINFO["pgrpid"] 当前进程的进程组ID。
PROCINFO["pid"] 当前进程的进程ID
PROCINFO["ppid"] 当前进程的父进程ID
PROCINFO["uid"] getuid(2)系统调用的值
PROCINFO["sorted_in"] 如果这个元素存在于PROCINFO中,那么它的值控制在 for循环中遍历数组元素的顺序。支持的值是“@ind_str_asc”、“@ind_num_asc”、“@val_type_asc”、“@val_str_asc”、“@ind_num_desc”、“@ ind_type_desc”、“@val_str_desc”、“@val_num_desc”和“@ unordered”。该值也可以是定义如下的任何比较函数的名称:
function cmp_func(i1, v1, i2, v2)
其中i1和i2为indices,v1和v2为被比较元素的对应值。它应该返回一个小于、等于或大于0的数字,这取决于数组元素的排序方式。
PROCINFO["version"] gawk的版本
RS 输入记录分隔符,默认是一个换行符。
RT 记录终止符。Gawk将RT设置为与RS指定的字符或正则表达式匹配的输入文本 。
RSTART 由match()匹配的第一个字符的索引;如果没有匹配,则为0。(这意味着字符索引从1开始。)
RLENGTH 由match()匹配的字符串的长度;如果没有匹配,则为-1.
SUBSEP 用于分隔数组元素中的多个下标的字符,默认为“\054”,即逗号',' 。
TEXTDOMAIN AWK程序的文本域;用于查找程序字符串的本地化翻译。
数组下标为方括号([和])之间的表达式。如果表达式是一个表达式列表(expr, expr…),那么数组下标就是一个字符串,由每个表达式(string)值的串联组成,由SUBSEP变量的值分隔。该设备用于模拟多维数组。例如:
i = "A"; j = "B"; k = "C"
x[i, j, k] = "hello, world\n"
将字符串“hello, world\n”赋值给数组x的元素,数组x以字符串“A\054B\054C“为索引。AWK中的所有数组都是关联的,即按字符串值建立索引。
特殊运算符in可用于测试数组是否有由特定值组成的索引:
if (val in array)
print array[val]
如果数组有多个下标,请使用 (i, j) in array。
in结构也可以在for循环中用于遍历数组的所有元素。
可以使用delete语句从数组中删除元素。delete语句也可以用来删除数组的全部内容,只需要指定数组名而不需要下标。
gawk支持真正的多维数组。它不要求这样的数组如在C或C++中一样是“矩形”。例如:
a[1] = 5
a[2][1] = 6
a[2][2] = 7
变量和字段可以是(浮点数),也可以是字符串,或者两者都是。变量的值如何解释取决于它的上下文。如果在数值表达式中使用,它将被视为一个数字;如果作为字符串使用,它将被视为字符串。
若要强制将一个变量视为一个数字,请向其添加0;若要强制将其视为字符串,请将其与空字符串连接起来。
当字符串必须转换为数字时,使用strtod(3)完成转换。通过使用CONVFMT的值作为sprintf(3)的格式字符串,并将变量的数值作为参数,以将数字转换为字符串。然而,尽管AWK中的所有数字都是浮点数,但是整数值总是被转换为整数。给出,
CONVFMT = "%2.2f"
a = 12
b = a ""
变量b的字符串值为“12”而不是“12.00” 。
注意:在POSIX模式下操作(例如使用--posix命令行选项)时,请注意区域设置可能会干扰十进制数字的处理方式:要传送到gawk的数字的十进制分隔符必须符合您的区域设置的预期,是逗号(,)还是句点(。)
Gawk执行如下比较:如果两个变量是数值的,那么它们将进行数值比较。如果一个值是数值型的,而另一个值的字符串值是“数值字符串”,那么比较也是数值型的。否则,数值将转换为字符串并执行字符串比较。当然,两个字符串作为字符串进行比较。
注意,字符串常量,如“57”,不是数字字符串,而是字符串常量。“数字字符串”的概念只适用于字段、getline输入、FILENAME、ARGV元素、ENVIRON元素以及由split()或patsplit()创建的数组中的数字字符串元素。基本思想是,user input,而且只有看起来是数字的用户输入,才应该这样对待。
未初始化的变量有数值0和字符串值“”(空字符串)。
您可以在AWK程序源代码中使用C-style的八进制和十六进制常量。例如,八进制值011等于十进制9,十六进制值0x11等于十进制17。
AWK中的字符串常量是双引号(如“value”)之间的字符序列。在字符串中,可以识别某些转义序列,如C中那样。如下所示:
\\ 反斜杠
\a “警报(alert)”字符;通常是ASCII BEL字符
\b 退格
\f 换页
\n 换行
\r 回车
\t 水平制表符
\v 垂直制表符
\xhex digits
跟在\x后面的十六进制数字字符串表示的字符。在ANSI C中,所有后面的十六进制数字都被认为是转义序列的一部分。(这个特性应该告诉我们一些关于委员会设计语言的事情。)例如,“\x1B”是ASCII ESC(escape)字符。
\ddd 八进制数的1位、2位或3位序列所表示的字符。例如,“\033”是ASCII ESC(escape)字符。
\c 字面意义上的字符c。
转义序列也可以在常量正则表达式中使用(例如,/[\t\f\n\r\v]/匹配空白字符)。
在兼容模式下,在正则表达式常量中使用八进制和十六进制转义序列表示的字符按字面意思处理。 因此,/a\52b/相当于/a\*b/。
?:前后并不一致!!
AWK是一种面向行的语言。先有模式,然后才是操作(action)。操作语句包含在{和}中。要么缺少模式,要么缺少操作,但当然不是两者都缺少。如果缺少模式,则对每个输入记录执行操作。一个缺少的操作相当于打印整个记录的{print}。
注释以#字符开始,并一直持续到行尾。空行可以用来分隔语句。通常,语句以换行结束,但是,以逗号、{、?、:、&&或||结束的行则不是这样。以do或else结尾的行也自动将它们的语句延续到下一行。在其他情况下,可以用“\”结尾来继续一行,在这种情况下忽略换行。 多个语句可以放在一行中,用“;”分隔它们。这既适用于模式-操作对(通常情况下)的操作部分中的语句,也适用于模式-操作语句本身。
AWK模式可以是下列模式之一:
BEGIN
END
BEGINFILE
ENDFILE
/regular expression/
relational expression
pattern && pattern
pattern || pattern
pattern ? pattern : pattern
(pattern)
! pattern
pattern1, pattern2
BEGIN和END是两种特殊的模式,它们不针对输入进行测试。所有BEGIN模式的操作部分被合并,就好像所有语句都是在一个BEGIN块中编写的一样。它们在读取任何输入之前执行。类似地,所有的END块都被合并,并在所有输入都耗尽时执行(或在执行exit语句时执行)。BEGIN和END模式不能与模式表达式中的其他模式组合。BEGIN和END模式不能缺少操作部分。
BEGINFILE和ENDFILE是附加的特殊模式,它们的主体在读取每个命令行输入文件的第一条记录之前和读取每个文件的最后一条记录之后执行。在BEGINFILE规则中,如果文件能够成功打开,ERRNO的值将是空字符串。否则,文件会有一些问题,代码应该使用nextfile跳过它。如果不这样做,gawk会为无法打开的文件产生通常的致命错误。
对于 /regular expression/模式,将对匹配正则表达式的每个输入记录执行关联语句。正则表达式与egrep(1)中的表达式相同,总结如下。
relational expression 可以使用下面关于操作部分中定义的任何操作符。它们通常测试某些字段是否匹配某些正则表达式。
&&, ||,和 ! 运算符分别是逻辑与、逻辑或和逻辑非,与C语言中一样。它们执行短路(shot-circuit)求值,(也与C语言中一样)并用于组合更原始的模式表达式。与大多数语言一样,括号可以用来改变求值的顺序。
?: 操作符与C中的操作符类似。如果第一个模式为真,那么用于测试的模式就是第二个模式,否则就是第三个模式。只计算第二和第三种模式中的一个。
表达式的pattern1、pattern2形式称为范围模式( range pattern)。它匹配所有输入记录,从匹配pattern1的记录开始,一直到匹配pattern2的记录(包括)。它不与任何其他类型的模式表达式相结合。
正则表达式是在egrep中找到的扩展类型。它们由以下字符组成:
c 匹配非元字符c.
\c 匹配字面意义的字符c.
. 匹配包括换行符在内的任何字符.
^ 匹配字符串的开始
$ 匹配字符串的结束
[abc...] 字符列表,匹配字符abc...中的任何一个。
[^abc...] 反字符列表,匹配除abc...之外的任何字符
r1|r2 交替,匹配r1或r2
r1r2 连接,匹配r1,然后是r2
r+ 匹配1个或多个r
r* 匹配0个或多个r
r? 匹配0个或1个r
(r) 分组:匹配r
r{n}
r{n,}
r{n,m} 大括号内的一个或两个数字表示一个区间表达式(interval expression)。如果大括号中有一个数字,前面的正则表达式r将重复n次。如果有两个数字之间用逗号隔开,r重复n到m次。如果有一个数字后面跟着逗号,那么r至少重复n次。
\y 匹配单词开头或末尾的空字符串。即匹配单词的边界,同于python中 \b
\B 匹配单词中空字符串。即匹配单词的非边界,同于python的 \B
\< 匹配单词开头的空字符串,即匹配单词的左边界
\> 匹配单词末尾的空字符串,即匹配单词的有边界
\s 匹配任何空白字符串
\S 匹配任何非空白字符串
\w 匹配任何单词组成字符(字母、数字或下划线)
\W 匹配任何非单词组成字符串
\` 匹配缓冲区(字符串)开头的空字符串
\' 匹配缓冲区末尾的空字符串。
在字符串常量中有效的转义序列(参见下面)在正则表达式中也有效
字符类(Character classes)是POSIX标准中引入的一个特性。字符类是一种特殊的符号,用于描述具有特定属性的字符列表,但实际字符本身可能因国家和/或字符集而异。例如,什么是字母字符的概念在美国和法国是不同的。
字符类仅在字符列表的方括号内的正则表达式中有效。字符类由[:,表示该类的关键字,和:]组成。POSIX标准定义的字符类有:
[:alnum:] 字母数字字符
[:alpha:] 字母字符
[:blank:] 空格或制表符
[:cntrl:] 控制字符
[:digit:] 数字字符
[:graph:] 既可打印又可见的字符。(空格是可打印的,但不可见,而a两者都是。)
[:lower:] 小写字母字符
[:print:] 可打印字符(不是控制字符的字符)
[:punct:] 标点字符(不是字母、数字、控制字符或空格字符的字符)
[:space:] 空格字符(如空格、制表符和formfeed等)。
[:upper:] 大写字母字符
[:xdigit:] 十六进制字符
例如,在POSIX标准之前,要匹配字母数字字符,必须编写/[A-Za-z0-9]/。如果您的字符集中有其他字母字符,那么它将不匹配它们,如果您的字符集与ASCII的排序方式不同,那么它甚至可能不匹配ASCII字母数字字符。使用POSIX字符类,您可以编写/[[:alnum:]]/,这将匹配字符集中的字母和数字字符,无论它是什么。
两个额外的特殊序列可以出现在字符列表中。这些字符集适用于非字符ASCII集,这些字符集可以有用多个字符表示的单个符号(称为排序元素--collating elements),以及用于排序(collating)或排序(sorting)目的的多个等效字符。(例如,在法语中,一个简单的“e”和一个带有庄重口音的“`”是等价的。)
Collating Symbols(排序的符号)
排序符号是包含在 [. 和 .] 中的多字符排序元素。例如,如果 ch 是一个排序元素,那么 [[.ch.]] 是匹配此排序元素的正则表达式,而 [ch] 是匹配 c 或 h 的正则表达式。
Equivalence Classes(等价类)
等价类是等价字符列表的特定于语言环境的名称。名称包含在 [= 和 =] 中。例如,名称e可以用来表示所有的“e,” “´,” 和“`.”。在本例中,[[=e=]]是一个正则表达式,它匹配 e, ´, 或`中的任何一个。
这些特性在非英语国家非常有用。gawk用于正则表达式匹配的库函数目前只能识别POSIX字符类;它们不识别排序符号(collating symbols)或等价类(equivalence classes)。
\y、\B、\<、\>、\s、\S、\w、\W、\` 和 \' 操作符是特定于gawk的;它们是基于GNU正则表达式库中的工具的扩展。
各种命令行选项控制gawk如何在正则表达式中解释字符。
No options
在默认情况下,gawk提供了上述的POSIX正则表达式和GNU正则表达式操作符的所有功能。
--posix
只支持POSIX正则表达式,GNU操作符并不特殊。(例如,\w匹配一个文字w)。
--traditional
匹配传统的Unix awk正则表达式。GNU操作符并不特殊,区间表达式也不可用。由八进制和十六进制转义序列描述的字符按字面处理,即使它们表示正则表达式元字符。
--re-interval
在正则表达式中允许间隔表达式,即使提供了--traditional选项。
Action语句包含在大括号 { 和 } 中。Action语句由大多数语言中常见的赋值、条件语句和循环语句组成。可用的操作符、控制语句和输入/输出语句都遵循C语言中的模式。
AWK中的操作符,按优先级递减的顺序是:
(...) 分组
$ 字段引用
++ -- 递增和递减,都可以作前缀和后缀
^ 取幂(也可以使用**,赋值运算符使用**=)
+ - ! 一元加,一元减和逻辑非
* / % 乘法、除法和取模(即求余)
+ - 加法和减法
space 字符串连接
| |& 用于getline、print和printf的管道I/O。
< > <= >= != ==
正则关系运算符
~ !~ 正则表达式匹配,反匹配。注意:不要在 ~ 或 !~ 的左边使用常量正则表达式(/foo/)。只在右边用一个。表达式/foo/ ~ exp与(($0 ~ /foo/) ~ exp)含义相同。这通常不是我们的本意。
in 数组成员
&& 逻辑与
|| 逻辑或
?: 三目运算
= += -= *= /= %= ^=
赋值。绝对赋值(var = value)和运算符赋值(其他形式)都受支持。
控制语句如下:
if (confition) statement [ else statement] 备注:可以嵌套,比如:if( ...){...} else if( ...){...} else{...}
while (condition) statement
do statement while (condition)
for (expr1;expr2;expr3) statement
break
continue
delete array[index]
delete array
exit [ expression ] { statement }
switch (expression) {
case value | regex : statement
...
[ default: statement ]
}
输入输出语句如下:
close(file [,how]) 关闭文件、管道或协同处理。可选的how只应在将双向管道的一端关闭到协同进程时使用。它必须是一个字符串值,要么是“to”,要么是“from”。
getline 从下一个输入记录设置$0;设置NF, NR, FNR。
getline <file 从file的下一个记录设置$0;设置NF。
getline var 从下一个输入记录设置var;设置 NR,FNR。
getline var <file 从file的下一个记录设置var
command | getline [var] 运行command将输出管道化为$0或var,如上所述。
command |& getline [var] 将command作为一个共同进程(co-process)运行,将输出管道化为$0或var,如上所述。共同进程是一个gawk的扩展。(command也可以是套接字。请参阅下面的 Special File Names 小节。)
next 停止处理当前输入记录。读取下一个输入记录,并从AWK程序中的第一个模式开始处理。如果到达输入数据的末尾,则执行END块(如果有)。
nextfile 停止处理当前输入文件。下一个读取的输入记录来自下一个输入文件。FILENAME和ARGIND被更新,FNR被重置为1,处理从AWK程序中的第一个模式开始。如果到达输入数据的末尾,则执行END块(如果有)。
print 打印当前记录。输出记录以ORS变量的值结束。
print expr-list 打印表达式。每个表达式由OFS变量的值分隔。输出记录以ORS变量的值结束。
print expr-list >file 在file中打印表达式。每个表达式由OFS变量的值分隔。输出记录以ORS变量的值结束。
printf fmt, expr-list 格式化和打印。请看下面的printf语句。
printf fmt, expr-list >file 在file上格式化和打印。
system(cmd-line) 执行命令cmd-line,并返回退出状态。(这可能在非POSIX系统上不可用)
fflush([file]) 刷新与打开的输出文件或管道文件关联的任何缓冲区。如果file丢失或为空字符串,则刷新所有打开的输出文件和管道。
允许对print和printf进行额外的输出重定向。
print ... >> file 追加输出到file
print ... | command 写在管道上。
print ... |& command 将数据发送到一个联合进程或套接字。(另见下文 Special File Names小节)。
getline命令成功时返回1,文件结束时返回0,出错时返回-1。在出现错误时,ERRNO包含一个描述问题的字符串
注意:打开双向套接字失败将导致返回调用函数的非致命错误。如果使用管道、联合进程或套接字来getline,或从循环中的print或printf来getline,则必须使用close()来创建命令或套接字的新实例。awk在返回EOF时不会自动关闭管道、套接字或联合进程
printf语句和sprintf()函数(请看下面)的AWK版本接受以下转换规范格式:
%c 一个字符。如果用于%c的参数是数字,则将其视为字符并打印。否则,参数被假定为字符串,并且只打印该字符串的第一个字符。 备注:python中 %c是把十进制ASSCII码(是一个整数)格式为对应的字符;
%d, %i 十进制数(整数部分)。
%e, %E [-]d.dddddde[+-]dd形式的浮点数。%E格式使用E而不是e。
%f, %F 格式为[-]ddd.dddddd的浮点数。如果系统库支持,%F也是可用的。这类似于%f,但是使用大写字母表示特殊的“非数字”和“无限”值。如果%F不可用,gawk将使用%f。
%g, %G 使用%e或%f转换,以较短者为准,并抑制不显著的零。%G格式使用%E而不是%e。
%o 无符号八进制数(也是整数)。
%u 无符号十进制数(同样是整数)。
%s 字符串。
%x, %X 无符号十六进制数(整数)。%X格式使用ABCDEF而不是abcdef。
%% 单个%字符;不转换任何参数。
可选的,附加参数可能位于%和控制字母之间:
count$ 此时在格式化中使用第count个参数。这称为位置说明符(positional specifier ),主要用于格式字符串的翻译版本,而不是AWK程序的原始文本。这是一个gawk扩展。
- 表达式应该在其字段内左对齐。
space 对于数值转换,使用空格作为正值的前缀,使用负号作为负值的前缀。
+ 加号用于宽度修饰符(见下文)之前,表示始终为数字转换提供一个符号,即使要格式化的数据是正的。+覆盖空格修饰符。
# 对某些控制字母使用“替代形式”。对于%o,提供一个前导0。对于%x和%X,为非零结果提供前导0x或0X。 对于%e、%E、%f和%F,结果总是包含小数点。对于%g和%G,不从结果中删除尾随的零。
0 前导0(zero)充当一个标志,表示输出应该用零填充而不是空格。这只适用于数字输出格式。只有当字段宽度大于要打印的值时,此标志才会生效。
width 字段应该填充到这个宽度。字段通常用空格填充。如果使用了0标志,则用0填充。
.prec 指定打印时使用的精度的数字。对于%e、%E、%f和%F格式,这指定要打印到小数点右侧的位数。对于%g和%G格式,它指定有效数字的最大数目。对于%d、%i、%o、%u、%x和%X格式,它指定要打印的最小位数。对于%s,它指定应该打印的字符串的最大字符数。
支持ANSI C printf()例程的动态width和prec功能。一个*代替width或prec规范,使它们的值从参数列表中取到printf或sprintf()。若要使用具有动态宽度或精度的位置说明符,请在格式字符串中*后面提供count$。例如,"%3$*2$.*1$s"。
当将I/O从print或printf重定向到文件,或通过getline从文件重定向时,gawk会在内部识别某些特殊的文件名。这些文件名允许访问从gawk的父进程(通常是shell)继承的打开的文件描述符。还可以在命令行上使用这些文件名来命名数据文件。这些文件名为:
/dev/stdin 标准输入
/dev/stdout 标准输出
/dev/stderr 标准错误输出
/dev/df/n 与打开的文件描述符n关联的文件。
这些对于错误消息特别有用。例如:
print "You blew it!" > "/dev/stderr"
否则你就得用:
print "Yow blew it!" | "cat 1>&2"
以下特殊文件名可与 |& co-process操作符一起用于创建TCP/IP网络连接:
/inet/tcp/lport/rhost/rport
/inet4/tcp/lport/rhost/rport
/inet6/tcp/lport/rhost/rport
本地端口lport上的TCP/IP连接到远程端口rport上的远程主机rhost的文件。使用0端口让系统选择一个端口。使用/inet4强制IPv4连接,使用/inet6强制IPv6连接。Plain /inet使用系统默认值(很可能是IPv4)。
/inet/udp/lport/rhost/rport
/inet4/udp/lport/rhost/rport
/inet6/udp/lport/rhost/rport
类似,但是使用UDP/IP而不是TCP/IP。
AWK有以下内置的算术功能:
atan2(y, x) 以弧度为单位返回y/x的反正切值。
cos(expr) 返回 (以弧度为单位的)expr 的余弦。
exp(epxr) 指数函数
int(expr) 截断为整数
log(expr) 自然对数函数
rand() 返回一个随机数N,在0和1之间,即0≤N < 1。
sin(expr) 返回 (以弧度为单位的)expr 的正弦。
sqrt(expr) 平方根函数
srand([expr]) 使用expr作为随机数生成器的新种子。如果不提供费用,使用一天的时间。返回值是随机数生成器的前一个种子。
Gawk 有如下内建的字符串函数:
asort(s [, d [, how ] ]) 返回源数组s中元素的数量。使用gawk比较值的常规规则对s的内容进行排序,并用以1开头的顺序整数替换排序后的值s的索引。如果指定了可选目标数组d,那么首先将s复制到d中,然后对d排序,保持源数组s的索引不变。可选字符串how控制方向和比较模式。how的有效值是对PROCINFO["sorted_in"]有效的任何字符串。它也可以是用户定义的如PROCINFO["sorted_in"]中所述的比较函数的名称。 备注:asort--对数组进行排序并保持索引关系。
asorti(s [, d [, how ] ]) 返回源数组s中的元素数量。其行为与asort()相同,只是数组索引(indices)用于排序,而不是数组值。当完成时,数组按数字索引,并且值是原始索引的值。原始值(即原数组的值)丢失;因此,如果希望保留原始数组,请提供第二个数组d。可选字符串how的用途与上面asort()中描述的相同。
gensub(r, s, h [, t]) 搜索目标字符串t,查找正则表达式r的匹配项。如果h是以g或G开头的字符串,则用s替换所有r的匹配项。如果不提供t,则使用$0。在替换文本s中,序列\n (n是1到9之间的数字)可以用来表示与第n个圆括号子表达式匹配的文本。序列\0表示整个匹配的文本,字符&也是如此。与sub()和gsub()不同,修改后的字符串作为函数的结果返回,而原始目标字符串不会更改。
gsub(r, s [, t ]) 对于字符串t中匹配正则表达式r的每个子字符串,替换字符串s,并返回替换的数量。如果不提供t,则使用$0。替换文本中的&被实际匹配的文本替换。使用\&获取文字&。(必须键入“\\&”;有sub()、gsub()和gensub()替换文本中的&和反斜杠规则的详细讨论,请参见GAWK: Effective AWK编程。)
index(s, t) 返回字符串s中字符串t的索引,如果不存在t,则返回0。(这意味着字符索引从1开始。)
length([s]) 返回字符串s的长度,或返回$0的长度(如果没有提供s)。作为一个非标准扩展,length()使用数组参数返回数组中元素的数量。
match(s, r [, a]) 返回正则表达式r在s中出现的位置,如果r不存在则返回0,并设置RSTART和RLENGTH的值。 请注意,参数顺序与~运算符:str ~ re相同。如果提供数组a,则清空a,然后用与r中相应的带圆括号的子表达式匹配的s部分填充元素1到n。a的第0个元素包含与整个正则表达式r匹配的s部分。下标a[n, "start"],和a[n, "length"]分别在字符串和长度中提供每个匹配子字符串的起始索引。
patsplit(s, a [, r [, seps] ]) 将字符串s拆分为数组a和正则表达式r上的分隔符数组seps,并返回字段的数量。元素值是s中与r匹配的部分。seps[i]的值是出现在a[i+1]前面的分隔符。如果省略r,则使用FPAT。首先清除数组a和seps。如上所述,使用FPAT进行拆分与字段拆分的行为相同。
split(s, a [, r [, seps] ]) 将字符串s拆分为数组a和正则表达式r上的分隔符数组seps,并返回字段的数量。如果省略r,则使用FS。首先清空数组a和seps。seps[i]是a[i]和a[i+1]之间由r匹配的字段分隔符。如果r是一个空格,那么s中的前导空格进入额外的数组元素seps[0],尾随空格进入额外的数组元素seps[n],其中n是split(s, a, r, seps)的返回值。拆分的行为与上述字段拆分相同。
sprintf(fmt, expr-list) 根据fmt打印expr-list,并返回结果字符串。
strtonum(str) 检查str,并返回其数值。如果str以前导0开头,则strtonum()假设str是一个八进制数。如果str以0x或0x开头,则strtonum()假设str是一个十六进制数。否则,假设为小数。
sub(r, s [, t ]) 就像gsub()一样,但是只替换第一个匹配的子字符串。
substr(s, i [, n ]) 返回从i开始的最多n个字符的s子字符串。如果省略n,则使用s的其余部分。
tolower(str) 返回字符串str的副本,将str中的所有大写字符转换为对应的小写字符。非字母字符保持不变。
toupper(str) 返回字符串str的副本,将str中的所有小写字符转换为对应的大写字符。非字母字符保持不变。
Gawk是多字节感知的。这意味着index()、length()、substr()和match()都是以字符而不是字节的形式工作的。
由于AWK程序的主要用途之一是处理包含时间戳信息的日志文件,所以gawk提供了以下函数来获取时间戳并对其进行格式化。
mktime(datespec)
将datespec转换为与systime()返回的格式相同的时间戳,并返回结果。datespec是YYYY MM DD HH MM SS[ DST ]格式的字符串。字符串的内容是六、七个数字,分别表示全年(包括世纪)、月份(从1到12)、月的天(从1到31)、小时(从0到23)、分钟(从0到59)、秒(从0到60)和可选的夏令时。这些数字的值不必在指定的范围内;例如,-1小时表示午夜前1小时。假定公历原点为零,0年在1年之前,-1年在0年之前。假定时间在当地时区。如夏令时标志为正,则假定时间为夏令时;如果为零,则假定时间为标准时间;如果为负(默认值),则mktime()尝试确定夏令时在指定的时间内是否有效。如果datespec没有包含足够的元素,或者生成的时间超出了范围,则mktime()返回-1。 备注:类似于python 中time模块的mktime()方法。
strftime([format [, timestamp[, utc-flag]]])
根据format中的规范格式化timestamp。如果utc-flag存在且非零或非空,则结果为UTC,否则结果为本地时间。timestamp应该与systime()返回的格式相同。如果缺少timestamp,则使用本天的当前时间。如果缺少format,则使用相当于date(1)输出的默认格式。默认格式在PROCINFO["strftime"]中可用。有关确保可用的格式转换,请参阅ANSI C中的strftime()函数的规范。
systime() 返回当前的时间,即从Epoch(POSIX系统上的UTC时间1970-01-01 00:00:00)开始的秒数。备注:类似python 中time模块中的time()方法。
Gawk提供以下位操作功能。它们通过将双精度浮点值转换为uintmax_t整数来工作,执行操作,然后将结果转换回浮点。功能包括:
and(v1, v2) 返回v1和v2提供的值的按位和(AND)。
compl(val) 返回val的按位补码。
lshift(val, count) 返回val左移count位后的值
or(v1, v2) 返回v1和v2提供的值的按位或(OR)。
rshift(val, count) 返回val右移count位后的值
xor(v1, v2) 返回v1和v2提供的值的按位异或(XOR)。
下面的函数用于多维数组。
isarray(x)
如果x是一个数组则返回true,否则返回false。
可以在AWK程序中使用以下函数在运行时转换字符串。有关详细信息,请参见GAWK:Effective AWK Programming。
bindtextdomain(directory [, domain])
指定gawk查找.mo文件的目录,以防它们不会或不能放在“标准”位置(例如,在测试期间)。它返回域(domain)被绑定的目录。默认域(doamin)是TEXTDOMAIN的值。如果目录是空字符串(""),那么bindtextdomain()返回给定域的当前绑定。
dcgettext(string [, domain [, category]])
返回区域设置类别category的文本域domain中字符串的转换。domain的默认值是TEXTDOMAIN的当前值。 category的默认值是“LC_MESSAGES”。
如果您为category提供一个值,那么它必须是一个字符串,该字符串必须等于GAWK: Effective AWK Programming中描述的已知区域设置类别中的一个。您还必须提供一个文本域。如果要使用当前域,请使用TEXTDOMAIN。
dcngettext(string1 , string2 , number [, domain [, category]])
返回用于本地类别category的文本域domain中string1和string2转换数的复数形式。domain的默认值是TEXTDOMAIN的当前值。 category的默认值是“LC_MESSAGES”。
如果您为category提供一个值,那么它必须是一个字符串,该字符串必须等于GAWK: Effective AWK Programming中描述的已知区域设置类别中的一个。您还必须提供一个文本域。如果要使用当前域,请使用TEXTDOMAIN。
AWK中的函数定义如下:
function name(parameter list) { statement }
函数在模式或操作中从表达式中调用时执行。函数调用中提供的实际参数用于实例化函数中声明的形式参数。数组通过引用传递,其他变量通过值传递。
由于函数最初不是AWK语言的一部分,所以为局部变量提供的方法相当笨拙:在参数列表中将它们声明为额外的参数。约定是通过参数列表中的额外空格将局部变量与实参数分离。例如:
function f(p, q, a, b) #a 和b是局部变量
{
...
}
/abc/ { ... ; f(1, 2) ; ... }
函数调用中的左括号必须紧跟函数名,不需要任何空格。这避免了连接操作符的语法歧义。此限制不适用于上面列出的内置函数。
函数可以相互调用,也可以是递归的。在函数调用时,将用作局部变量的函数参数初始化为null字符串和数字0。
使用return expr从函数返回值。如果没有提供值,或者函数通过“falling off”结尾返回,则返回值是未定义的。
作为gawk扩展,可以间接调用函数。为此,将要调用的函数的名称作为字符串赋给一个变量。然后使用此变量,就像它是一个函数的名称一样,前面加上@符号,就像这样:
function myfunc()
{
print "myfunc called"
...
}
{ ...
the_func = "myfunc"
@the_func() # call through the_func to myfunc
...
}
如果提供了--lint,gawk将在解析时而不是在运行时警告对未定义函数的调用。在运行时调用未定义的函数是一个致命错误。
func这个词可以代替function。
您可以动态地向正在运行的gawk解释器添加新的内置函数。详细内容超出本手册的范围;有关详细信息,请参见GAWK:Effective AWK Programming。
extension(object, function)
动态链接由object命名的共享对象文件,并调用该对象中的function来执行初始化。它们都应该作为字符串提供。返回function返回的值。
在C级使用这个特性并不好,但它不太可能消失。在某个时候可能会添加其他机制。
pgawk接受两个信号。SIGUSR1使它将配置文件和函数调用堆栈转储到配置文件,配置文件可以是awkprof.out,也可以是使用--profile选项命名的任何文件。然后它继续运行。SIGHUP导致pgawk转储配置文件和函数调用堆栈,然后退出。
字符串常量是用双引号括起来的字符序列。在非英语环境中,可以将AWK程序中的字符串标记为需要翻译成本地自然语言。这些字符串在AWK程序中用一个前导下划线(" _ ")标记。例如,
gawk 'BEGIN { print "hello, world" }'
总是打印hello,world。但是,
gawk 'BEGIN { print _"hello, world" }'
在法国可能打印 bonjour, monde。
生成和运行可本地化的AWK程序涉及几个步骤。
国际化特性在GAWK: Effective AWK Programming中有详细描述。
gawk的主要目标是与POSIX标准以及最新版本的UNIX awk兼容。为此,gawk集成了以下用户可见的特性,这些特性在AWK书中没有描述,但是它们是Bell实验室版本AWK的一部分,并且在POSIX标准中。
该书指出,当awk以文件的形式打开参数时,命令行变量赋值将发生在BEGIN块执行之后。然而,在早期的实现中,当这样的赋值出现在任何文件名之前时,赋值将发生在BEGIN块运行之前。应用程序逐渐依赖于这个“特性”。当awk更改为与其文档匹配时,程序执行前分配变量的-v选项被添加进来,以适应依赖于旧行为的应用程序。(这个特性得到了贝尔实验室和GNU开发人员的一致同意。)
在处理参数时,gawk使用特殊选项“--”来表示参数的结束。在兼容模式下,它会发出警告,但会忽略未定义的选项。在正常操作中,这些参数被传递给AWK程序以供其处理。
AWK书没有定义srand()的返回值。POSIX标准让它返回它使用的种子,以便跟踪随机数序列。因此,gawk中的srand()也返回它当前的种子。
其它新功能包括:使用多个-f选项(来自MKS awk);ENVIRON数组;\a和\v转义序列(最初在gawk中完成,并反馈到贝尔实验室版本中);tolower()和toupper()内置函数(来自Bell实验室版本);以及printf中的ANSI C转换规范(首先在贝尔实验室版本中完成)。
gawk支持的历史AWK实现有一个特性:可以调用length()内置函数,不仅不带参数,甚至不带括号!因此,
a = length # Holy Algol 60, Batman!
与下面两者任一相同:
a = length()
a = length($0)
使用这个功能是不好的实践,如果在命令行中指定了--lint, gawk会发出关于其使用的警告。
Gawk对POSIX awk有许多扩展。本节将对它们进行描述。通过使用--traditional或--posix选项调用gawk,可以禁用这里描述的所有扩展。
下面的gawk功能在POSIX awk 中不可用。
1. 不会对通过-f选项命名的文件执行路径搜索。因此,AWKPATH环境变量不是特殊的。
2. 没有用于文件包含的工具(gawk的@include机制)。
3. \x 转义序列(用--posix 禁用)
4. ? 和 : 之后继续行的能力(用--posix 禁用)
5. AWK 中的八进制和十六进制常量。
6. ARGIND, BINMODE, ERRNO, LINT, RT 和TEXTDOMAIN变量不是特殊的。
7. IGNORECASE变量及其副作用不可用。
8. FIELDWIDTHS变量和固定宽度字段拆分。
9. 基于字段值的FPAT变量和字段拆分。
10. PROCINFO数组不可用。
11. RS作为正则表达式的使用。
12. 无法识别可用于I/O重定向的特殊文件名。
13. 用于创建协同进程的 |& 操作符。
14. BEGINFILE和ENDFILE特殊模式不可用。
15. 使用空字符串作为FS的值,并作为split()的第三个参数来拆分单个字符的能力。
16. split()的第四个可选参数,用于接收分隔符文本。
17. close()函数的第二个可选参数。
18. match()函数的第三个可选参数。
19. 在printf和sprintf()中使用位置说明符的能力。
20. 将数组传递给length()的能力。
21. 使用delete array 删除数组全部内容的能了。
22. 使用nextfile放弃对当前输入文件的处理。
23. and(), asort(), asorti(), bindtextdomain(), compl(), dcgettext(), dcngettext(), gensub(), lshift(), mktime(), or(), patsplit(), rshift(), strftime(), strtonum(), systime() 和xor() 函数。
24. 本地化的字符串。
25. 使用extension()动态的添加新的内建函数。
AWK书没有定义close()函数的返回值。Gawk的close()分别在关闭输出文件或管道时从fclose(3)或pclose(3)返回值。它在关闭输入管道时返回进程的退出状态。如果指定的文件、管道或协进程没有使用重定向打开,则返回值为-1。
当使用--traditional选项调用gawk时,如果-F选项的fs参数是“t”,那么FS被设置为制表符。注意,键入gawk -F\t …简单地使shell引用“t”,而不将“\t”传递给-F选项。由于这是一个相当丑陋的特殊情况,所以它不是默认行为。如果指定了--posix,也不会发生这种行为。要真正获得一个制表符作为字段分隔符,最好使用单引号:gawk -F'\t' …
AWKPATH环境变量可用于提供一个 当通过-f和--file选项查找命名的文件时 gawk搜索的目录列表。
对于套接字通信,可以使用两个特殊的环境变量来控制重试的次数(GAWK_SOCK_RETRIES)和重试之间的间隔(GAWK_MSEC_SLEEP)。间隔的单位是毫秒。在不支持usleep(3)的系统上,该值四舍五入为整数秒。
如果环境中存在POSIXLY_CORRECT,那么gawk的行为就像命令行中指定了--posix一样。如果--lint已被指定,gawk将为此发出警告消息。
如果exit语句与一个值一起使用,则gawk将使用给定的数值退出。
否则,如果在执行期间没有问题,gawk将使用C常量EXIT_SUCCESS的值退出。这通常是0。
如果发生错误,gawk将以C常量EXIT_FAILURE的值退出。这通常是1。
如果gawk因致命错误退出,则退出状态为2。在非POSIX系统上,这个值可以映射为EXIT_FAILURE。
这个手册页文档gawk,4.0版本。
运算符 | 描述 |
---|---|
(...) | 分组 |
= += -= *= /= %= ^= **= | 赋值。绝对赋值(var = value)和运算符赋值(其他形式)都受支持。 |
?: | C条件表达式 |
|| | 逻辑或 |
&& | 逻辑与 |
~ 和 !~ | 正则表达式匹配,反匹配。注意:不要在 ~ 或 !~ 的左边使用常量正则表达式(/foo/)。只在右边用一个。表达式/foo/ ~ exp与(($0 ~ /foo/) ~ exp)含义相同。这通常不是我们的本意。 |
< <= > >= != == | 关系运算符 |
空格 | 字符串连接 |
| |& | 用于getline、print和printf的管道I/O |
+ - | 加,减 |
* / % | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ ** | 求幂 |
++ -- | 增加或减少,作为前缀或后缀 |
$ | 字段引用 |
in | 数组成员 |
变量 | 描述 |
---|---|
$n | 当前记录的第n个字段,字段间由FS分隔 |
$0 | 完整的输入记录 |
ARGC | 命令行参数的数目(不包括gawk选项或程序源代码) |
ARGIND | 正在处理的当前文件在ARGV中的索引。(命令行参数数组ARGV的索引是从0开始) |
ARGV | 包含命令行参数的数组 |
CONVFMT | 数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组 |
ENVIRON | 包含当前环境值的数组。数组以环境变量为索引,每个元素都是该变量的值(例如,environmenton ["HOME"]可能是/home/arnold)。更改此数组不会影响 通过重定向或system()函数生成的gawk程序所看到的环境。 |
ERRNO | 如果系统错误发生在为getline执行重定向、读取getline或close()期间,则ERRNO将包含描述错误的字符串。该值受非英语地区翻译的限制 |
FIELDWIDTHS | 以空格分隔的字段宽度列表。设置好后,gawk将输入解析为固定宽度的字段,而不是使用FS变量的值作为字段分隔符。 |
FILENAME | 当前文件名 |
FNR | 当前输入文件中输入记录数。即各文件分别计数的行号 |
FS | 字段分隔符(默认是任何空格) |
IGNORECASE | 控制所有正则表达式和字符串操作的大小写敏感性。如果IGNORECASE有一个非零值,则当执行正则表达式操作时,在规则中进行字符串比较和模式匹配,使用FS和FPAT进行字段拆分,使用RS进行记录分隔,使用~和!~匹配正则表达式,以及gensub()、gsub()、index()、match()、patsplit()、split()和sub()内置函数都忽略大小写。 注意:数组下标不受影响。但是,asort()和asorti()函数会受到影响。 因此,如果IGNORECASE不等于零,/aB/匹配所有字符串“aB”、“aB”、“aB”和“aB”。与所有AWK变量一样,IGNORECASE的初值为零,因此所有正则表达式和字符串操作通常区分大小写。 |
LINT | 在AWK程序中提供--lint选项的动态控制。如果是真的,gawk会打印lint警告。当是假的时候,它不会。当指定字符串值"fatal"时,lint警告将变成致命错误,就像--lint=fatal一样。任何其他真值只打印警告。 |
NF | 当前输入记录中的字段数。或者一条记录的字段数 |
NR | 到目前为止所看到的输入记录的总数。即已经读出的记录数,就是行号,从1开始 |
OFMT | 数字的输出格式(默认值是%.6g) |
OFS | 输出字段分隔符,默认是一个空格。 |
ORS | 输出记录分隔符(默认值是一个换行符) |
RLENGTH | 由match()匹配的字符串的长度;如果没有匹配,则为-1. |
RS | (输入)记录分隔符(默认是一个换行符) |
RT | (输入)记录终止符。Gawk将RT设置为与RS指定的字符或正则表达式匹配的输入文本 。 |
RSTART | 由match()匹配的第一个字符的索引;如果没有匹配,则为0。(这意味着字符索引从1开始。) |
SUBSEP | 用于分隔数组元素中的多个下标的字符,默认为“\054”,即逗号',' 。 |
实例2:输出已读取的记录数(即行号NR)以及所读取的记录在当前输入文件的记录数(即在当前文件的行号FNR)
实例3:指定输出分隔符