gawk

模式扫描与处理语言


语法格式

gawk [-f program] [-F fs] [-v var=val] [-W opts] [--] 'program-text' files

命令简介

gawk是GNU版的AWK编程语言,遵循POSIX 1003.1语言标准,在AWK编程语言(A.Kernighan等著)的基础上开发的,增加了UNIX SVR4 awk的扩展特性,以及GNU特定的扩展特性。

gawk顺序读取输入文件中的数据,根据命令行或AWK程序文件中提供的一组模式/动作语句,检索匹配的数据行,按照相应的动作进行处理。在命令行上提供AWK程序代码时,前后必须加单引号,保护其免受Shell提前解释。如果未指定文件,或指定的输入文件为“-”,则从标准输入中读取数据。

注意,“-W”选项主要用于实现POSIX标准定义的特性。

命令选项

-f program, --file=program  从指定的程序文件(而非第一个命令行参数)中读取AWK程序代码。注意,命令行中可以同时指定多个“-f”选项。

-F fs, --field-separator=fs  使用fs作为输入字段分隔符,取代FS变量的值。例如,“-F '\t'”表示使用制表符作为字段分隔符。

-v var=val, --assign var=val  在程序开始执行之前,把指定的数值val赋予指定的变量var。这些变量值可用于AWK程序的BEGIN代码块。

-W compat, -W traditional, --compat, --traditional  以兼容模式运行。在此情况下,gawk等同于UNIX的awk,不能处理GNU特定的扩充特性。

-W dump-variables[=file], --dump-variables[=file]  把已排序的全局变量列表,包括变量的名字、类型和当前值等写到指定的文件中。如果未指定文件名,默认的文件是当前目录中的awkvars.out文件。在运行大型AWK程序时,可以使用这个选项调试程序。

-W exec file, --exec file  类似于“-f”选项,用于读取指定文件中的AWK程序源代码。但存在两个差别:一是终止gawk处理其他选项,即“--exec”选项只能是命令行的最后一个选项,如果命令行中还存在其他选项,将作为参数直接传递给gawk命令;二是禁止命令行的变量赋值。注意,这个选项主要适用于CGI应用,且应与“#!”脚本一起使用,防止把选项、赋值或AWK源代码传递给CGI应用。

-W help, -W usage, --help, --usage  显示命令的简单说明、用法、语法格式与选项说明等帮助信息,然后退出。

-W posix, --posix  启用POSIX兼容模式,支持POSIX正则表达式,但施加了下列限制(其他限制详见gawk手册页):

-W re-interval, --re-interval 允许在正则表达式中使用区间表达式。由于传统的awk不支持区间表达式,默认情况下gawk也不支持,以防止早期的AWK程序无法正常运行。

-W source awkcode, --source awkcode  允许命令行中的源代码awkcode与指定文件中的源代码混合使用。尤其当命令行中的AWK源代码需要用到“-f”选项指定文件中自定义的函数时,必须指定“--source”选项。

-W version, --version  显示命令的版本与版权等信息,然后正常退出。

--  表示命令选项到此结束(允许AWK程序参数的首字符为“-”字符)。

AWK程序的执行

AWK程序由一系列模式/动作语句和选用的函数定义组成:

pattern      { action statements }
function name(parameter list) { statements }

gawk首先读取“-f”选项指定程序文件或者命令行上直接给出的源代码,把这些代码组合在一起,形成一个完整的AWK 程序。

“-f”选项可以在命令行中使用多次。这种用法有助于用户建立自己的AWK函数库,以便随时调用,不必在每个新的AWK程序中都重写AWK函数。

在获取“-f”选项指定的源文件时,可以使用AWKPATH环境变量指定的检索路径,除非指定的源文件为绝对路径名。如果变量不存在,默认的检索路径是“.:/usr/local/share/awk”。

gawk按照下列顺序执行AWK程序。首先执行“-v”选项指定的所有变量赋值,其次把AWK程序编译成内部形式,然后执行BEGIN代码块(如果存在)中的语句。接着依次读取命令行中指定(位于ARGV数组变量中)的每个文件。如果命令行中没有指定任何文件,gawk转而读取标准输入。

命令行文件参数位置如果存在“var=val”形式的赋值,gawk需要在运行代码块之后开始处理变量赋值。命令行的动态变量赋值是非常有用的,使AWK能够灵活控制如何处理输入数据,把输入数据解释成字段和记录等。

如果ARGV数组的某个元素值为空串,gawk将会直接跳过,转而处理下一个输入文件。

对于每一个输入记录,gawk将会依序测试AWK程序中的每一个模式,确定两者是否匹配。对于输入记录匹配的每一个模式,依次执行相关的动作。

最终,在处理完所有的输入记录之后,gawk开始执行END代码块(如果存在)中的语句。

变量、记录与字段

AWK变量是动态的,无须事先定义,使用时直接引入即可。根据引用位置,变量的值可以是一个浮点数或字符串。AWK支持一维数组,但也可以模拟多维数组。AWK提供若干预定义的内置变量,可在运行AWK程序时引用。详见后续介绍。

记录

记录相当于数据行,通常以换行符为分隔符。通过定义内置变量RS,用户也可以控制怎样分割记录。如果RS变量值是任何一个单字符,使用该字符作为记录分隔符。否则把RS看作一个正则表达式。输入数据中匹配此正则表达式的字符串可以作为记录分隔符。然而在兼容模式中,只有其中的第一个字符才能作为记录分隔符。如果把RS设置成空串,则使用空行作为记录分隔符。在此情况下,除了FS变量的设置之外,总是使用换行符作为附加的字段分隔符。

字段

在读取每个输入记录时,gawk使用FS变量的值作为字段分隔符,把记录分割成一系列字段。如果FS变量值是任何一个单字符,则使用该字符作为字段分隔符。如果FS变量值是一个空串,则每个字符都是一个单独的字段。如果FS变量值是单个空格,则一个或多个空格、制表符或换行符均可作为字段分隔符。注意,FS变量值也可以是一个正则表达式,如果FS及RS变量值是一个正则表达式,IGNORECASE变量的值将会影响字段的划分,以及记录的分割。

如果FIELDWIDTHS变量已设置为由空格分隔的一组数字,意味着每个字段具有固定的宽度,gawk使用指定的宽度分割记录。此时忽略FS变量的设置。

重新赋予FS变量一个新值将会抵消FIELDWIDTHS变量的作用,恢复默认的处理方式。

利用$1,$2,…等位置参数,也可以引用输入记录中的每一个字段($0是整个记录)。

读取每个记录时,gawk将会把NF变量设置成记录的字段总和。

引用不存在的字段时(字段号大于$NF)将会得到一个空串。但是,如果把值赋予一个不存在的字段(如$(NF+2) = 5),将会增加NF变量的值,并创建必要的中间字段,同时赋予空值,重新设置$0变量的值,使之包括OFS变量值分割的所有字段。如果使用负数引用字段,将会引起致命的错误。

如果减少NF变量的值,将会导致字段的丢失,并重新设置$0变量的值,使之包括OFS变量值分割的现有字段。

如果赋予现有任何字段一个数值,在引用$0时,将会引起整个记录的重建。类似地,如果赋予$0一个新值,将会引起记录的重新分割,并分别赋予每个字段一个新值。

内置变量

ARGC  命令行参数的数量(不包括gawk的命令选项)。

ARGIND  ARGV中当前处理的文件的索引。

ARGV  命令行参数数组。数组的索引从0到ARGC-1。动态地修改ARGV变量的值能够控制使用哪一个输入数据文件。

CONVFMT  数值的转换格式,默认的数值转换格式为“%.6g”。

ENVIRON  一个包含当前环境变量值的关联数组。数组的索引是环境变量的名字,数组元素是相应环境变量的值。例如,ENVIRON["HOME"]是用户的主目录。

ERRNO  在运行AWK程序期间,如果出现系统错误,ERRNO变量将包含一个错误描述的字符串。

FIELDWIDTHS  由空格分隔的一组表示字段宽度的数字。当设置此变量时,gawk将会把输入数据解析成固定宽度的字段,而不是使用FS变量的值作为字段分隔符。

FILENAME  当前输入文件的名字。如果命令行中未指定文件,变量的值为“-”。但在BEGIN代码块中,FILENAME是未定义的(除非利用getline语句予以设置)。

FNR  当前输入文件中的输入记录号。

FS  输入字段分隔符,默认值为空格。

IGNORECASE  用于控制所有正则表达式或字符串操作是否区别大小写字母。如果IGNORECASE变量值非0,则字符串比较、模式匹配、FS变量定义的字段分割、RS变量定义的记录分割、“~”与“!~”的正则表达式匹配,以及gensub()、gsub()、index()、match()、split()和sub()等内置函数均忽略大小写字母的差别。注意,数组下标不受影响,但asort()和asorti()函数受影响。IGNORECASE变量的默认值为0。故所有正则表达式和字符串操作通常均区别大小写字母。

NF  当前输入记录的字段数量。

NR  迄今处理的输入记录总和。

OFMT  数值的输出格式,默认的数值输出格式为“%.6g”。

OFS  输出字段分隔符,默认值为空格。

ORS  输出记录分隔符,默认值为换行符。

RS  输入记录分隔符,默认值为换行符。如果RS变量值是一个空串,输入记录可由空行分割。作为GNU的扩展特性,也可以使用正则表达式作为输入记录分隔符。在POSIX兼容模式下,只有RS变量值的第一个字符用作输入记录分隔符。

RT  每读一次数据,设置一次RT变量,其中含有由RS变量界定的当前输入数据记录。

RSTART  match()返回的匹配字符串的第一个字符的索引。0表示没有匹配(这也蕴含着字符索引从1开始)。

RLENGTH  match()返回的匹配字符串的长度。-1表示没有匹配。

SUBSEP  数组下标分隔符,默认值为“\034”,即逗号“,”。

数组

数组是一种组合变量,利用数组名后面方括号中的下标表达式,可以引用每一个数组元素。下标可以是数字、字符或字符串。所有的下标均可看作字符串,即便数字也是如此,而且也不要求数组元素是连续的。通过赋值即可创建一个数组。例如,下列赋值语句表示创建了一个具有两个元素的数组x:

x[8] = "eight"
x[A] = "ABCDEFG"

gawk支持一维数组。如果下标由多个表达式(中间加SUBSEP变量定义的分隔符,默认为逗号“,”)组成,如“[expr, expr, ...]”,则可以仿真一个多维数组。例如,下列语句表示创建一个三维数组x,同时把字符串“hello, world\n”赋予由下标“i, j, k”索引的一个数组元素:

x[i, j, k] = "hello, world\n"

在AWK程序中,所有数组均为关联数组,也就是说,数组是由字符串索引的(即下标为字符串)。

一个特殊的运算符“in”可用于测试数组是否具有指定的数组元素,即指定的数值是否是一个合法的数组下标。例如:

if (val in array)
  print array[val]

如果数组具有多个下标,例如,假定数组array是一个二维数组,则可以使用“(i, j) in array”表达式测试数组元素。

“in”运算符可在for循环中使用,用于遍历所有的数组元素。

使用delete语句可以删除一个数组元素。如果数组名后面不加下标,也可以使用delete语句删除整个数组及其数据内容。

变量类型与转换

变量和字段可以是整数、浮点数或字符串。怎样解释变量的值取决于上下文。如果用于数值表达式,则按数值处理;如果用于字符串表达式,则按字符串处理。

为了强制按数值解释和处理变量,可以把一个0加到变量中。为了强制按字符串解释和处理变量,可以使用一个空串连接变量。当需要把字符串转换成数值时,gawk利用strtod(3)函数实现。当需要把数值转换成字符串时,gawk使用CONVFMT变量的值作为sprintf(3)的格式字符串实现。

在比较两个变量时,gawk首先尝试按变量的数值大小比较两个变量,否则按字符串的顺序比较两个变量。

在计算变量的值时,根据上下文环境,未初始化变量的值或者是0,或者是空串。

八进制与十六进制数值常数

从3.1版的gawk开始,可以在AWK程序的源代码中使用C语言风格的八进制或十六进制数值的常数。例如,010等价于十进制的8,0x10等价于十进制的16等。

字符串常数

在AWK程序中,字符串常数由一系列字符组成,前后加双引号。在字符串常数中,可以包含下列转义字符:

\\  单个斜线字符。

\a  警示音。

\b  退格符。

\f  换页符。

\n  换行符。

\r  回车。

\t  制表符。

\v  纵向制表符。

\xhh  一或两位十六进制数值编码表示的字符。例如,\x1B是ASCII字符ESC。

\nnn  一、二或三位八进制数值编码表示的字符。例如,\033是ASCII字符ESC。

\c  表示任何一个普通字符本身。

上述转义字符可作为字符常数出现在正则表达式中,例如,“/[ \t\f\n\r\v]/”能够匹配空格、制表符和换行符等空白字符。

在传统的兼容模式中,正则表达式常数中使用的八进制或十六进制转义字符按其表示的字符本身处理, 例如,“/a\52b/”等价于“/a\*b/”。

模式与动作

AWK是一个面向数据行处理的语言。在AWK程序中,首先出现的是模式,然后是动作。动作语句应使用花括号括起来。模式可以不存在,动作也可以省略,当然,两者不能同时消失。如果省略了模式,对于每一个输入记录,都需要执行动作语句。如果动作语句不存在,默认的动作等价于“{ print }”语句(表示输出整个记录)。

注释行以“#”开始,一直可以延续到行尾。空行可用于分隔语句。通常,语句以换行符结束,但以“,”、“{”、“?”、“:”、“&&”或“||”字符结束的代码行除外。此外,以“do”或“else”结束的代码行,其后续语句也会自动延续到下一行。如同其他编程语言一样,在代码行后面附加一个反斜线字符“\”,也可以把超长部分延续到下一行。

一个代码行可以出现多个语句,中间加分号“;”分隔符。这既适用于模式/动作对(正常情况)的动作部分中的语句,也适用于模式/动作语句本身。

模式

AWK程序支持下列模式:

BEGIN
END
/regular expression/
relational expression
pattern && pattern
pattern || pattern
pattern ? pattern : pattern
(pattern)
! pattern
pattern1, pattern2

BEGIN与END是两种特殊的模式,不需要测试输入数据。多个BEGIN模式中的所有动作部分可以合并到一起,就像所有语句都写在一个BEGIN代码块中一样。BEGIN代码块是在读取任何输入数据之前开始执行的。

类似地,所有END代码块也可以合并到一起,在所有的输入处理完之后开始执行(或在执行某个语句之后开始执行)。注意,BEGIN与END模式中不能省略动作部分。

使用“/…/”形式的正则表达式模式时,对于每个匹配正则表达式的输入记录,执行相关的动作语句。

关系表达式通常用于测试某个字段是否匹配指定的正则表达式。

“&&”、“||”和“!”运算符分别是逻辑与、逻辑或和逻辑非,用于组合基本的模式表达式。

如同大多数语言一样,圆括号用于修改计算的优先顺序。

“? :”运算符类似于C语言中的同一运算符。如果第一个模式为真,使用第二个模式进行匹配测试,否则使用第三个模式进行匹配测试。

pattern1, pattern2”形式的表达式称作范围模式,能够匹配从匹配第一个模式pattern1的输入记录开始直至匹配第二个模式pattern2的输入记录之间的所有输入记录。

正则表达式

正则表达式是一种字符串描述,用于匹配检索对象的相应字符串。一个正则表达式可以是一个普通字符、一个转义字符、一个句点“.”、一个方括号表达式或表达式的各种组合。gawk采用扩展的正则表达式,简列如下:

c  匹配非元字符c,其中c可以是任何一个普通字符。

\c  转义符号用于抑制特殊字符,用于匹配任何字符c,不管是普通字符,还是特殊字符。例如,“\$”仅匹配美元符号“$”字符本身。

.  匹配任何一个单字符,包括换行符。

^  匹配行首的空串,即匹配位于行首的任何字符或字符串。例如,“^#”匹配行首以“#”为起始字符的字符串,如“#include”。

$  匹配行尾的空串。例如,“\\$”表示匹配任何以单个反斜线字符“\”结尾的数据行。“\.$”表示匹配任何以句点“.”结尾的数据行。

*  表示在检索匹配的字符串时,前面的正则表达式应重复0次或尽可能多次。例如,“t.*ing”能够匹配“ting”、“thing”和“thought of going”等。星号“*”运算符仅重复先前最少单位的正则表达式,如一个字符,如果需要重复较大的表达式,可以使用圆括号组织子表达式(注意,圆括号前应加转义符号“\”)。

+  类似于星号“*”,表示前面的正则表达式至少必须重复1次。例如,“cho+se”能够匹配“chose”和“choose”等。

?  类似于星号“*”,表示前面的正则表达式只能重复0次或1次。例如,“fr?ee”只能匹配“fee”和“free”等。

[list]  字符集合。匹配其中列举的任何一个字符。

[^list]  字符集合的补集。匹配字符集合之外的其他任何字符。

(re)  圆括号用于组合正则表达式,使之作为一个整体,或作为正则表达式中的一个子表达式。

re1re2  匹配正则表达式re1re2的连接。

|  逻辑或运算符是一种“交替”匹配,用于表示两者均可或任选其一的匹配。例如,“re1|re2”能够匹配re1re2。在所有的正则表达式运算符中,“|”的优先级最低。

{m}  区间表达式。数字m表示前面的正则表达式应当重复匹配m次。

{m,}  区间表达式。数字m加逗号表示前面的正则表达式至少应当重复匹配m次。

{m,n} 区间表达式。数字mn(中间加逗号分隔符)表示前面的正则表达式应当重复匹配mn次。

注意,仅当指定了“--posix”或“--re-interval”选项,才能使用上述区间表达式。

\y  匹配单字左右边缘的空串。例如,“\ya”能够匹配age或air等单词,“e\y”能够匹配same或come等单词。

\B  匹配单字非边缘字符位置的空串。例如,“\Bm”或“m\B”能够匹配same或come等单词。

\<  匹配字首的空串。例如,“\<wo”能够匹配word、world和would等单词。

\>  匹配字尾的空串。例如,“it\>”能够匹配exit、Exit、quit和Quit等单词。

\w  匹配构成单词的任何字符,包括字母、数字或下画线。

\W  匹配非单词构成的字符,即除字母、数字和下画线之外的其他任何字符。

\`  匹配缓冲区(字符串)起始位置前的空串。

\’  匹配缓冲区(字符串)结束位置后的空串。

注意,上述的特殊表达式(“\y”、“\B”、“\<”、“\>”、“\w”、“\W”、“\‘”和“\’”)是gawk的扩充特性,是基于GNU正则表达式库函数实现的正则表达式。

gawk也支持POSIX定义的标准字符类。字符类是一种特殊的表示方式,用于描述一组具有特定属性的字符,但在不同的语言环境或不同的字符集中,其中包含的实际字符会有所变化。

字符类只能用于方括号字符集合中的正则表达式。POSIX标准定义的字符类如下:

[:alnum:]  字母与数字。

[:alpha:]  字母。

[:blank:]  空格或制表符。

[:cntrl:]  控制字符。

[:digit:]  数字字符。

[:graph:]  可打印或可视字符(空格为可打印字符但非可视字符)。

[:lower:]  小写字母。

[:print:]  可打印字符(非控制字符)。

[:punct:]  标点符号字符(字母、数字、控制字符和空白字符之外的字符)。

[:space:]  空白字符,如空格、制表符或换页符等。

[:upper:]  大写字母。

[:xdigit:]  十六进制数字。

例如,如果没有POSIX标准定义的字符类,若想匹配字母数字,需要写出这样的正则表达式:“/[A-Za-z0-9]/”,如果是非ASCII字符集,写起来可能还要复杂,利用POSIX字符类,可以简写为“/[[:alnum:]]/”,而且不必考虑语言环境或字符集,总是能够匹配任何字母数字。

注意,命令行选项控制了gawk怎样解释正则表达式中的字符。

在未加任何选项的默认情况下,gawk支持POSIX正则表达式和GNU正则表达式(“\y”、“\B”、“\<”、“\>”、“\w”、“\W”、“\‘”和“\’”),但不支持区间表达式。

如果指定了“--posix”选项,gawk仅支持POSIX正则表达式与区间表达式,但不支持GNU正则表达式,也就是说,“\w”仅匹配w本身,而非任何字母、数字和下画线。

如果指定了“--traditional”选项,gawk仅支持传统的UNIX awk正则表达式,不支持GNU正则表达式、区间表达式和POSIX字符类。八进制和十六进制转义序列表示的字符按字符本身处理,即使是一个正则表达式的元字符。

动作

动作语句前后需要增加花括号。动作语句通常包括类似于C语言的常规赋值语句、条件测试语句和循环语句等,运算符、控制语句和输入/输出语句也是如此。

运算符

AWK支持的运算符如下(优先级依次降低):

(...)  按组运算。

$  字段引用。

++, --  自增与自减运算,包括引用前和应用后的自增与自减。

^  指数运算(也可以使用“**”作为指数运算符)。

+, -, !  一元加、一元减和逻辑非运算。

*, /, %  乘、除和模运算。

+, -  加和减运算。

空格  字符串连接运算。

|, |&  用作getline、print和printf等语句的管道I/O。

<, >, <=, >=, !=, ==  关系运算。

~, !~  正则表达式的匹配与不匹配。例如,“$0 ~ /UNIX/”表示测试$0中是否存在匹配UNIX的子串。

in  数组元素测试。

&&  逻辑与运算。

||  逻辑或运算。

?:  条件表达式,其形式为“expr1 ? expr2 : expr3”。如果表达式expr1为真,则整个表达式的值是expr2,否则是expr3(仅计算expr2expr3二者之一)。

=, +=, -=, *=, /=, %=, ^=  赋值运算(包括扩展的赋值运算)。

控制语句

if (condition) statements [ else statements ]

while (condition) statements

do statement while (condition)

for (expr1; expr2; expr3) statements

for (var in array) statements

break

continue

delete array[index]

delete array

exit [ expression ]

{ statements }

I/O语句

close(file [, how])  关闭指定的文件、管道或协进程。选用的参数how只能用于关闭协进程两路管道的一端,且必须是一个字符串“to”或“from”。

getline  读取下一个输入记录,用之设置$0,同时设置NF、NR和FNR变量。如果成功地读取了下一个记录,返回1;如果遇到文件结束标志(EOF),返回0;如果出现错误,返回-1,此时ERRNO会包含一个错误描述字符串。

getline <file  使用文件中的下一个输入记录设置$0,同时设置NF变量。

getline var  使用下一个输入记录设置指定的变量var,同时设置NR和FNR变量。

getline var <file  使用文件中的下一个输入记录设置指定的变量var

cmd | getline [var]  运行指定的命令,利用管道,把命令的输出写入$0或var,同时设置必要的变量。

cmd |& getline [var]  作为一个协进程,运行指定的命令,利用管道,把命令的输出写入$0或var,同时设置必要的变量。

next  停止处理当前的输入记录。读取下一个输入记录,利用AWK程序的第一个模式开始处理。如果遇到输入数据结束标志,执行END代码块(如果存在)。

nextfile  停止处理当前的输入文件。从下一个输入文件中读取下一个输入记录,更新FILENAME与ARGIND变量,把FNR重置为1。然后利用AWK程序的第一个模式开始处理。如果遇到输入数据结束标志,执行END代码块(如果存在)。

print  输出当前的记录。输出记录采用ORS变量的值作为其终止符。

print expr-list  输出表达式的值。每个表达式采用OFS变量的值作为分隔符。输出记录采用ORS变量的值作为其终止符。

print expr-list >file  把表达式的值写入指定的文件。每个表达式采用OFS变量的值作为分隔符。输出记录采用ORS变量的值作为其终止符。

printf fmt, expr-list  按照自定义的格式输出表达式的值。

printf fmt, expr-list >file  按照自定义的格式,把表达式的值写入指定的文件。

system(cmd-line)  执行指定的命令,然后返回命令的结束状态(非POSIX兼容的系统不能用)。

fflush([file])  腾空打开的输出文件或管道文件的任何缓冲区。如果未指定文件,默认的文件为标准输出。如果指定的文件名是一个空串,意味着腾空所有打开的输出文件和管道文件的缓冲区。

注意,对于print和下面介绍的printf而言,把输出改向到一个文件也是允许的,例如:

print ... >> file  把输出数据追加到指定文件的后面。

print ... | cmd  利用管道,把输出数据传递给指定的命令。

print ... |& cmd  把输出数据送交协进程或套接字。

printf语句

在AWK支持的printf语句与sprintf()函数中,格式字符串fmt可以由C语言风格的格式定义组成。格式字符串前后必须加引号。

%c  单个ASCII字符。如果%c对应的参数是数值,则按字符处理和显示。如果参数是一个字符串,则仅显示其中的第一个字符。

%d, %i  前者表示十进制数值,后者表示十进制数值的整数部分。

%e, %E  前者表示[-]d.dddddde[+-]dd形式的浮点数。%E类似于%e,只是用E替代e。

%f, %F  前者表示[-]ddd.dddddd形式的浮点数。如果系统支持,%F类似于%f,使用大写字母处理和输出诸如“not a number”和“infinity”之类的数值。如果%F不可用,则转用%f。

%g, %G  使用%e或%f转换格式,选取其最短者,且删除无效数字0。%G使用%E替代%e。

%o  无符号的八进制整数值。

%u  无符号的十进制整数值。

%s  字符串。

%x, %X  无符号的十六进制整数值。前者使用小写字母abcdef,后者使用大写字母ABCDEF。

%%  单个百分号字符。

注意,当使用整数格式控制字符转换一个超出C语言长整数范围的数值时,gawk转用%0f 格式。

必要时,可以在百分号“%”与控制字符之间增加下列参数:

-  在其字段位置左对齐表达式的值。

空格  对于数值转换而言,正数前加一个空格前缀,负数前加一个减号“-”。

+  如果在“宽度”参数前增加一个加号“+”,表示数值之前总是需要加一个符号,即使结果是一个正数。加号“+”的有效性级别高于“空格”。

#  采用适当的前缀或其他控制。例如,对于%o,提供前置0,对于%x和%X,分别提供前置0x或0X(非0数值),对于%e、%E、%f和%F,输出的结果总是包含一个小数点。对于%g和%G,保留结果后面的0。

0  作为一个标志,前置0表示输出应当填充适当数量的0而非空格。这个参数也适用于非数值输出格式。注意,仅当字段宽度大于输出的数值时,这个参数才有效。

width  一个数字,指定字段的宽度。数值达不到字段宽度时通常应填充适当数量的空格。如果指定了标志0,表示应填充适当数量的0。

.prec  一个数字,指定输出时使用的精度。对于%e、%E、%f和%F格式,指定的是输出数值小数点右边的数字位数。对于%g和%G格式,指定的是最大有效数字的位数。对于%d、%o、%i、%u、%x和%X格式,指定的是输出数值的最少数字位数。对于%s格式,指定的是应当输出的字符串的最大字符数量。

除了上述格式定义之外,格式字符串中还可以使用“\n”或“\t”等常用的转义字符来控制输出的格式。实际上,格式字符串中也可以插入空格等其他普通字符,作为间隔控制或字符串常数一同输出。注意,除非在格式字符串明确增加“\n”换行符,printf语句与sprintf()函数等不会自动附加换行符。

特殊文件名

gawk支持下列特殊文件,可用于print或printf语句以及getline函数等的I/O重定向。实际上,这些特殊文件也可以用作gawk命令行的文件名参数。

/dev/stdin  标准输入。

/dev/stdout  标准输出。

/dev/stderr  标准错误输出。例如,“print "something wrong!" > "/dev/stderr"”语句表示通过标准错误输出显示错误信息。

/dev/fd/n  引用文件描述符为n的文件。其中n是gawk继承自父进程(Shell)的文件描述符。

数学函数

AWK支持下列内置数学函数:

atan2(y, x)  返回y/x(单位弧度)的余切值。

cos(expr)  返回表达式(单位弧度)的余弦值。

exp(expr)  指数函数。返回以e为底数、expr为指数的幂。

int(expr)  返回表达式的整数部分。

log(expr)  返回表达式的自然对数。

rand()  返回一个位于0与1之间的随机数N(0≤N < 1)。

sin(expr)  返回表达式(单位弧度)的正弦值。

sqrt(expr)  返回表达式的平方根。

srand([expr]) 使用expr作为随机数生成器的新种子。如果省略了expr,默认值是当前的日期和时间。返回值是先前提供的种子。

字符串函数

AWK支持下列内置字符串函数:

asort(s [, d])  返回源数组s的数组元素数量。使用gawk的常规规则对数组s的内容进行排序,排序后的数组s使用顺序的整数(从1开始)替代其索引。如果指定了目的数组d,首先把数组s的内容复制到数组d,然后对数组d进行排序。源数组s的索引保持不变。

asorti(s [, d])  返回源数组s的数组元素数量。但与asort()函数不同的是,这里只是对数组的索引而非数组的值进行排序。排序后,数组按照新的顺序索引而成,打乱了原始索引与数组元素值的对应关系,从而导致原始数组的错乱。如果需要保持源数组的原貌,可提供一个目的数组d

gensub(r, s, h [, t])  检索目标字符串t中是否存在匹配正则表达式r的子串。如果字符串h的首字符为g或G,使用字符串s替换匹配r的所有子串。否则,如果h是一个数值,表示使用s替换第h个匹配r的子串。如果省略了t,使用$0作为目标字符串。如果替换字符串s中含有字符序列“\i”(i是数字1~9),表示匹配第i个子表达式的子串,“\0”表示匹配的整个字符串(其作用相当于下面即将介绍的“&”字符)。与sub()和gsub()不同的是,gensub()仅仅返回替换后的结果,原始的目标字符串保持不变。

gsub(r, s [, t])  使用字符串s替换目标字符串t中匹配正则表达式r的每一个子串,返回替换了多少次。如果省略了t,使用$0作为目标字符串。如果替换字符串s中存在一个“&”字符,“&”引用的是匹配的子串。使用匹配的子串替换“&”字符后,再使用扩展后的字符串s进行替换。若想使用“&”字符本身,可加转义符号“\”,如“\&”(实际必须写作“\\&”)。

index(s, t)  返回字符串t在字符串s中的索引。如果s中不存在t,则返回0(字符索引从1开始)。

length([s])  返回字符串s的长度。如果未提供字符串s,返回$0的长度。从3.1.5版开始,如果参数是一个数组,返回数组元素的数量。

match(s, r [, a])  返回匹配正则表达式r的子串在目标字符串s中出现的位置。如果不存在则返回0。设置RSTART和RLENGTH变量的值。注意,参数的顺序与“~”运算符的顺序相同:“str ~ re”。如果提供了数组a,首先清除a,然后把匹配r中相应子表达式的子串赋予数组元素1至数组元素na的第0个数组元素包含目标字符串s中匹配整个表达式r的子串。数组元素a[n, "start"]和a[n, "length"]分别提供每一个匹配的子串在目标字符串s中的起始索引或长度。

split(s, a [, r])  根据正则表达式r,把字符串s分割成多个字段,赋予数组a,返回字段的数量(赋值前首先清除数组)。如果省略了r,使用FS的值作为字段分隔符。

sprintf(fmt, exprs)  计算一个或多个表达式参数,按照指定的格式fmt返回表达式的计算结果。返回的结果等同于使用同样的参数调用printf()函数。

strtonum(str)  考察字符串str,返回相应的数值。如果str的首字符为0,则假定str是一个八进制的数字。如果str以0x或0X开始,则假定str是一个十六进制的数字。

sub(r, s [, t])  恰如gsub(),但仅替换第一个匹配的字符串。

substr(s, i [, n])  返回字符串s中从指定位置i开始的最多n个字符的子串。如果n省略,返回字符串s的所有剩余部分。

tolower(str)  返回给定字符串str的副本,把其中的大写字母转换成相应的小写字母,非字母的字符保持不变。

toupper(str)  返回给定字符串str的副本,把其中的小写字母转换成相应的大写字母,非字母的字符保持不变。

从3.1.5版开始,gawk支持多字节的字符,这意味着index()、length()、substr()和match()函数均以字符(而非字节)为单位处理字符串。

时间函数

AWK程序的一个主要用途是处理包含时间信息的日志文件,故gawk提供下列函数,以便获取时间,执行必要的格式转换等:

mktime(datespec)  类似于systime()函数,只是返回从UNIX纪元(1970-01-01 00:00:00 UTC)开始至datespec参数指定的日期与时间为止的累计时间量(单位为秒)。datespec参数是一个字符串,形如“YYYY MM DD HH MM SS[ DST]”,由6个或7个数值组成,分别表示完整的年份、月(1~12)、日(1~31)、小时(0~23)、分(0~59)和秒(0~60)。最后一个选用的数值是夏时制标志。指定的时间假定是本地时间。如果夏时制标志是一个正数,假定指定的时间是夏时制时间。如果是0,假定指定的时间是标准时间。如果是负数(默认),mktime()需要确定指定的时间是否应做夏时制时间调整。如果提供的时间参数不完整,或指定的时间超出范围,mktime()返回-1。

strftime([format [, timestamp[, utc-flag]]])  按照指定的格式规范返回时间。如果utc-flag存在,且既不是0,又非空串,则显示UTC时间,否则显示当地时间。timestamp参数与systime()函数的返回值相同。如果省略了timestamp参数,则使用当前的日期与时间。如果省略了format参数,默认的时间格式等同于date命令的输出格式。

systime()  返回自UNIX纪元(1970-01-01 00:00:00 UTC)开始至当前日期与时间为止的累计时间量(单位为秒)。

二进制数据位操作函数

从3.1版开始,gawk支持下列按位操作的函数:

and(v1, v2)  返回双精度浮点数参数v1v2按位与的运算结果。

compl(val)  返回双精度浮点数参数val按位求补的运算结果。

lshift(val, count)  返回双精度浮点数参数val左移count位之后的结果。

or(v1, v2)  返回双精度浮点数参数v1v2按位或的运算结果。

rshift(val, count)  返回双精度浮点数参数val右移count位之后的结果。

xor(v1, v2)  返回双精度浮点数参数v1v2按位异或的运算结果。

用户定义的函数

除了gawk提供的函数之外,用户还可以在AWK程序中定义自己的函数。自定义函数的语法格式 如下:

function name(parameter-list) { statements }

其中,name是函数的名字,函数名与左圆括号之间不能有空格,parameter-list是0个或多个参数,参数之间需加逗号分隔符,statements可以是任何gawk语句。

在模式或动作中,当使用参数引用函数名时,即开始调用函数。除了数组按地址传递之外,其他变量都是按值传递的。

函数可以相互调用,也可以递归调用。

在函数体内,可以使用return语句,返回函数的处理或计算结果。return语句的语法格式如下:

return [expression]

其中,表达式expression是选用的,如果省略,返回值是不确定的。不管是否返回数据,return语句标志当前函数执行的结束。

应用实例

1. 使用冒号作为字段分隔符,按字母顺序显示系统中的所有用户列表。

$ gawk -F ":" '{ print $1 | "sort" }' /etc/passwd

2. 模拟实现“wc -l”命令,对输入文件的行数进行计数。

$ gawk '{ nlines++ }
> END { print nlines }' /etc/profile
68
$

3. 模拟实现nl命令,在每个输出的数据行之前插入一个行号。

$ gawk '{ printf "% 6i\t%s\n", FNR, $0 }' /etc/passwd

4. 模拟date命令,说明如何调用自定义的函数ctime。

$ cat ctime
function ctime(format)
{
        if (format == "")
            format = "%a %b %d %H:%M:%S %Z %Y"          # use default format
        ts = systime()                                                  # use current time
        return strftime(format, ts)
}
$ echo "current time is" | gawk --source '{printf "%s %s\n", $0, ctime("")}' -f ctime
current time is  Mon Apr 09 07:09:15 CST 2012
$ echo "current time is" | gawk --source '{printf "%s %s\n", $0, ctime("%c")}' -f ctime
current time is  Mon Apr  9 07:19:26 2012
$

索引:A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z