awk [ -F Ere ] [ -v Assignment ] ... { -f ProgramFile | 'Program' } [ [ File ... | Assignment ... ] ] ...
awk 命令利用一组用户提供的指令来将一组文件和用户提供的扩展正则表达式比较,一次一行。然后在任何与扩展正则表达式匹配的行上执行操作。awk 处理的最大记录大小为 10KB。
awk 命令的模式搜索比 grep 命令的搜索更常用,且它允许用户在输入文本行上执行多个操作。awk 命令编程语言不需要编译,并允许用户使用变量、数字函数、字符串函数和逻辑运算符。
awk 命令受到 LANG、LC_ALL、LC_COLLATE、LC_CTYPE、LC_MESSAGES、LC_NUMERIC、NLSPATH 和 PATH 环境变量的影响。
本章中包括以下主题:
awk 命令采取两种类型的输入:输入文本文件和程序指令。
搜索和操作在输入文本文件上执行。文件如下指定:
如果用 File 变量指定多个文件,则文件以指定的顺序处理。
用户提供的指令控制 awk 命令的操作。这些指令来自命令行的‘Program’变量或来自用 -f 标志和 ProgramFile 变量一起指定的文件。如果指定多个程序文件,这些文件以指定的顺序串联,且使用指令的生成的顺序。
awk 命令从输入文本文件中的数据产生三种类型的输出:
可以在同一个文件上执行所有三种类型的输出。awk 命令识别的编程语言允许用户重定向输出。
文件以下列方式处理:
awk 编程语言中的 BEGIN 语句允许用户指定在读取第一个记录前要执行的一组指令。这对于初始化特殊变量特别有用。
记录是由记录分隔符隔开的一组数据。记录分隔符的缺省值是换行字符,它使文件中的每一行成为一个单独的记录。记录分隔符可以通过设置 RS 特殊变量来更改。
命令指令可以指定应比较记录内的特定字段。缺省情况下,字段由空白区(空格或跳格)隔开。每个字段由一个字段变量表示。记录中的第一个字段指定为 $1 变量,第二个字段指定为 $2 变量,以此类推。整个记录指定为 $0 变量。字段分隔符可以通过在命令行使用 -F 标志或通过设置 FS 特殊变量来更改。FS 特殊变量可以设置为下列值:空格、单个字符或扩展正则表达式。
awk 编程语言中的 END 语句允许用户指定在读取最后一个记录后要执行的操作。这对于发送有关 awk 命令完成了什么工作的消息特别有用。
awk 命令编程语言由以下格式的语句构成:
Pattern { Action }
如果一个记录与指定模式相匹配,或包含与该模式匹配的字段,则执行相关的操作。可以指定没有操作的模式,这种情况下,包含该模式的整行写至标准输出。为每个输入记录执行指定的没有模式的操作。
在 awk 命令语言语法中使用四种类型的模式:
awk 命令使用的扩展正则表达式类似于 grep 或 egrep 命令使用的表达式。扩展正则表达式的最简单的形式就是包括在斜杠中的一串字符。例如,假定一个名为 testfile 的文件具有以下内容:
smawley, andy smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis
输入以下一行命令:
awk '/smi/' testfile
将把包含 smi 字符串的具体值的所有记录打印至标准输出。在这个示例中,awk 命令的程序 '/smi/' 是一个没有操作的模式。输出是:
smiley, allen smith, alan smithern, harry smithhern, anne smitters, alexis
以下特殊字符用于形成扩展正则表达式:
awk 命令识别大多数用于 C 语言约定中的转义序列,以及 awk 命令本身用作特殊字符的几个转义序列。转义序列是:
转义序列 | 表示的字符 |
---|---|
\" | \"(双引号)标记 |
\/ | /(斜杠)字符 |
\ddd | 其编码由 1、2 或 3 位八进制整数表示的字符,其中 d 表示一个八进制数位 |
\\ | \ ( 反斜杠 ) 字符 |
\a | 警告字符 |
\b | 退格字符 |
\f | 换页字符 |
\n | 换行字符(请参阅以下的注) |
\r | 回车字符 |
\t | 跳格字符 |
\v | 垂直跳格 |
注:除了在 gsub、match、split 和 sub 内置函数中,扩展正则表达式的匹配都基于输入记录。记录分隔符字符(缺省情况下为换行字符)不能嵌套在表达式中,且没与记录分隔符字符匹配的表达式。如果记录分隔符不是换行字符,则可与换行字符匹配。在指定的四个内置函数中,匹配基于文本字符串,且任何字符(包含记录分隔符)可以嵌套在模式中,这样模式与适当的字符相匹配。然而,用 awk 命令进行的所有正则表达式匹配中,在模式使用一个或多个 NULL(空)字符将生成未定义的结果。
关系运算符 <(小于)、>(大于)、<=(小于或等于)、>=(大于或等于)、= =(等于)和 !=(不等于)可用来形成模式。例如,模式:
$1 < $4
将与第一个字段小于第四个字段的记录匹配。关系运算符还和字符串值一起使用。例如:
$1 =! "q"
将与第一个字段不是 q 的所有记录匹配。字符串值还可以根据校对值匹配。例如:
$1 >= "d"
将与第一个字段以字符 a、b、c 或 d 开头的所有记录匹配。如果未给出其它信息,则字段变量作为字符串值比较。
可以使用三种选项组合模式:
/begin/,/end/
与包含字符串 begin 的记录以及该记录和包含字符串 end 之间的所有记录(包含包括字符串 end 的记录)匹配。
$1 == "al" && $2 == "123"
与第一个字段是 al 且第二个字段是 123 的记录匹配。
用 BEGIN 模式指定的操作在读取任何输入之前执行。用 END 模式指定的操作在读取了所有输入后执行。允许多个 BEGIN 和 END 模式,并以指定的顺序处理它们。在程序语句中 END 模式可以在 BEGIN 模式之前。如果程序仅由 BEGIN 语句构成,则执行操作且不读取输入。如果程序仅由 END 语句构成,则在任何操作执行前读取所有输入。
有多种类型的操作语句:
操作语句括在 { } (花括号) 中。如果语句指定为没有模式,则它们在每个记录上执行。在括号里可以指定多个操作,但操作间必须以换行字符或 ;(分号)分隔,且语句以它们出现的顺序处理。操作语句包含:
算术语句 |
算术运算符 +(加号), - (减号), / (除号), ^ (幂), * (乘号), % (系数)用于格式:
表达式 运算符 表达式 这样,语句: $2 = $1 ^ 3
将第一个升为三次方的字段的值指定给第二个字段。 |
一元语句 |
一元 -(减号)和一元 +(加号)如在 C 编程语言中操作:
+Expression 或 -Expression |
增量和减量语句 |
增量前语句和减量前语句如在 C 编程语言中操作:
++Variable 或 --Variable 增量后语句和减量后语句如在 C 编程语言中操作: Variable++ 或 Variable-- |
字符串串联语句 |
字符串值可以通过紧挨着陈述来串联。例如:
$3 = $1 $2 将字段变量 $1 和 $2 中的字符串的串联指定给字段变量 $3。 |
awk 命令语言使用算术函数、字符串函数和一般函数。如果打算编写一个文件,且稍后在同一个程序里读取它,则 close 子例程语句是必需的。
以下算术函数执行与 C 语言中名称相同的子例程相同的操作:
字符串函数是:
gsub( Ere, Repl, [ In ] ) | 除了正则表达式所有具体值被替代这点,它和 sub 函数完全一样地执行,。 |
sub( Ere, Repl, [ In ] ) | 用 Repl 参数指定的字符串替换 In 参数指定的字符串中的由 Ere 参数指定的扩展正则表达式的第一个具体值。sub 函数返回替换的数量。出现在 Repl 参数指定的字符串中的 &(和符号)由 In 参数指定的与 Ere 参数的指定的扩展正则表达式匹配的字符串替换。如果未指定 In 参数,缺省值是整个记录($0 记录变量)。 |
index( String1, String2 ) | 在由 String1 参数指定的字符串(其中有出现 String2 指定的参数)中,返回位置,从 1 开始编号。如果 String2 参数不在 String1 参数中出现,则返回 0(零)。 |
length [(String)] | 返回 String 参数指定的字符串的长度(字符形式)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。 |
blength [(String)] | 返回 String 参数指定的字符串的长度(以字节为单位)。如果未给出 String 参数,则返回整个记录的长度($0 记录变量)。 |
substr( String, M, [ N ] ) | 返回具有 N 参数指定的字符数量子串。子串从 String 参数指定的字符串取得,其字符以 M 参数指定的位置开始。M 参数指定为将 String 参数中的第一个字符作为编号 1。如果未指定 N 参数,则子串的长度将是 M 参数指定的位置到 String 参数的末尾 的长度。 |
match( String, Ere ) | 在 String 参数指定的字符串(Ere 参数指定的扩展正则表达式出现在其中)中返回位置(字符形式),从 1 开始编号,或如果 Ere 参数不出现,则返回 0(零)。RSTART 特殊变量设置为返回值。RLENGTH 特殊变量设置为匹配的字符串的长度,或如果未找到任何匹配,则设置为 -1(负一)。 |
split( String, A, [Ere] ) | 将 String 参数指定的参数分割为数组元素 A[1], A[2], . . ., A[n],并返回 n 变量的值。此分隔可以通过 Ere 参数指定的扩展正则表达式进行,或用当前字段分隔符(FS 特殊变量)来进行(如果没有给出 Ere 参数)。除非上下文指明特定的元素还应具有一个数字值,否则 A 数组中的元素用字符串值来创建。 |
tolower( String ) | 返回 String 参数指定的字符串,字符串中每个大写字符将更改为小写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
toupper( String ) | 返回 String 参数指定的字符串,字符串中每个小写字符将更改为大写。大写和小写的映射由当前语言环境的 LC_CTYPE 范畴定义。 |
sprintf(Format, Expr, Expr, . . . ) | 根据 Format 参数指定的 printf 子例程格式字符串来格式化 Expr 参数指定的表达式并返回最后生成的字符串。 |
一般函数是:
close( Expression ) | 用同一个带字符串值的 Expression 参数来关闭由 print 或 printf 语句打开的或调用 getline 函数打开的文件或管道。如果文件或管道成功关闭,则返回 0;其它情况下返回非零值。如果打算写一个文件,并稍后在同一个程序中读取文件,则 close 语句是必需的。 |
system(Command ) | 执行 Command 参数指定的命令,并返回退出状态。等同于 system 子例程。 |
Expression | getline [ Variable ] | 从来自 Expression 参数指定的命令的输出中通过管道传送的流中读取一个输入记录,并将该记录的值指定给 Variable 参数指定的变量。如果当前未打开将 Expression 参数的值作为其命令名称的流,则创建流。创建的流等同于调用 popen 子例程,此时 Command 参数取 Expression 参数的值且 Mode 参数设置为一个是 r 的值。只要流保留打开且 Expression 参数求得同一个字符串,则对 getline 函数的每次后续调用读取另一个记录。如果未指定 Variable 参数,则 $0 记录变量和 NF 特殊变量设置为从流读取的记录。 |
getline [ Variable ] < Expression | 从 Expression 参数指定的文件读取输入的下一个记录,并将 Variable 参数指定的变量设置为该记录的值。只要流保留打开且 Expression 参数对同一个字符串求值,则对 getline 函数的每次后续调用读取另一个记录。如果未指定 Variable 参数,则 $0 记录变量和 NF 特殊变量设置为从流读取的记录。 |
getline [ Variable ] | 将 Variable 参数指定的变量设置为从当前输入文件读取的下一个输入记录。如果未指定 Variable 参数,则 $0 记录变量设置为该记录的值,还将设置 NF、NR 和 FNR 特殊变量。 |
注:所有 getline 函数的格式对于成功输入返回 1,对于文件结束返回零,对于错误返回 -1。
用户定义的函数以下列格式说明:
function Name (Parameter, Parameter,...) { Statements }
函数可以指向 awk 命令程序中的任何位置,且它的使用可以优先于它的定义。此函数的作用域是全局的。
函数参数可以是标量或数组。参数名称对函数而言是本地的;所有其它变量名称都是全局的。同一个名称不应用作不同的实体;例如,一个参数名称不能用作函数名称又用作特殊变量。具有全局作用域的变量不应共享一个函数的名称。同个作用域中的标量和数组不应具有同一个名称。
函数定义中的参数数量不必和调用函数时使用的参数数量匹配。多余的形式参数可用作本地变量。额外的标量参数初始化后具有等同于空字符串和数字值为 0(零)的字符串值;额外的数组参数初始化为空数组。
当调用函数时,函数名称和左括号之间没有空格。函数调用可以是嵌套的或循环的。从任何嵌套的或循环函数函数调用返回时,所有调用函数的参数的值应保持不变,除了引用传送的数组参数。return 语句可用于返回一个值。
在函数定义内,在左 { ( 花括号 ) 之前和右 } ( 花括号 ) 之后的换行字符是可选的。
函数定义的一个示例是:
function average ( g,n) { for (i in g) sum=sum+g[i] avg=sum/n return avg }
数组 g 和变量 n 以及数组中的元素个数传递给函数 average。然后函数获得一个平均值并返回它。
awk 命令编程语言中的大部分条件语句和 C 编程语言中的条件语句具有相同的语法和功能。所有条件语句允许使用{ } (花括号) 将语句组合在一起。可以在条件语句的表达式部分和语句部分之间使用可选的换行字符,且换行字符或 ;(分号)用于隔离 { } (花括号) 中的多个语句。C 语言中的六种条件语句是:
awk 命令编程语言中的五种不遵循 C 语言规则的条件语句是:
awk 命令编程语言的两种输出语句是:
需要以下语法:
print [ ExpressionList ] [ Redirection ] [ Expression ] print 语句将 ExpressionList 参数指定的每个表达式的值写至标准输出。每个表达式由 OFS 特殊变量的当前值隔开,且每个记录由 ORS 特殊变量的当前值终止。 可以使用 Redirection 参数重定向输出,此参数可指定用 >(大于号)、>>(双大于号)和 |(管道)进行的三种输出重定向。Redirection 参数指定如何重定向输出,而 Expression 参数是文件的路径名称(当 Redirection 参数是 > 或 >> 时)或命令的名称(当 Redirection 参数是 | 时)。 |
|
printf | 需要以下语法:
printf Format [ , ExpressionList ] [ Redirection ] [ Expression ] printf 语句将 ExpressionList 参数指定的表达式以 Format 参数指定的格式写至标准输出。除了 c 转换规范(%c)不同外,printf 语句和 printf 命令起完全相同的作用。Redirection 和 Expression 参数与在 print 语句中起相同的作用。 对于 c 转换规范:如果自变量具有一个数字值,则编码是该值的字符将输出。如果值是零或不是字符集中的任何字符的编码,则行为未定义。如果自变量不具有数字值,则输出字符串值的第一个字符;如果字符串不包含任何字符,则行为未定义。 |
注:如果 Expression 参数为 Redirection 参数指定一个路径名称,则 Expression 参数将括在双引号中以确保将它当作字符串对待。
变量可以是标量、字段变量、数组或特殊变量。变量名称不能以数字开始。
变量可仅用于引用。除了函数参数以外,它们没有明确说明。未初始化的标量变量和数组元素具有一个为 0(零)的数字值和一个为空字符串(" ")的字符串值。
根据上下文,变量呈现出数字或字符串值。每个变量可以具有数字值和/或字符串值。例如:
x = "4" + "8"
将值 12 指定给变量 x。对于字符串常量,表达式应括在 " "(双引号)标记中。
数字和字符串间没有显式转换。要促使将表达式当作一个数字,向它添加 0(零)。要促使将表达式当作一个字符串,则添加一个空字符串(" ")。
字段变量由 $(美元符号)后跟一个数字或数字表达式来表示。记录中的第一个字段指定为 $1 变量,第二个字段指定为 $2,以次类推。$0 字段变量指定给整个记录。新字段可以通过指定一个值给它们来创建。将一个值指定给不存在的字段(即任何大于 $NF 字段变量的当前值的字段)将促使创建任何干扰字段(指定为空字符串),增加 NF 特殊变量的值,并促使重新计算 $0 记录变量。新字段由当前字段分隔符(FS 特殊变量的值)隔开。空格和跳格是缺省字段分隔符。要更改字段分隔符,请使用 -F 标志或 在 awk 命令程序中为 FS 特殊变量指定另一个值。
数组初始为空且它们大小可动态更改。数组由一个变量和在 [ ](方括号)中的下标来表示。下标或元素标识符可以是几个字符串,它们提供了一种相关数组能力。例如,程序:
/red/ { x["red"]++ } /green/ { y["green"]++ }
增加 red 计数器和 green 计数器的计数。
数组可以用一个以上的下标来建立索引,类似于一些编程语言中的多维数组。因为 awk 命令的编程数组实际上是一维的,通过串联各独立表达式的字符串值(每个表达式由 SUBSEP 环境变量的值隔开)来将以逗号隔开的下标转换为单个字符串。所以,以下两个索引操作是等同的:
x[expr1, expr2,...exprn]
和
x[expr1SUBSEPexpr2SUBSEP...SUBSEPexprn]
当使用 in 运算符时,一个多维 Index 值应包含在圆括号之中。除了 in 运算符,任何对不存在数组元素的引用将自动创建该元素。
以下变量对于 awk 命令具有特殊含义:
ARGC | ARGV 数组中的元素个数。此值可以更改。 |
ARGV | 其每个成员包含 File 变量之一或 Assignment 变量之一的数组按序从命令行取出,并从 0(零)编号至 ARGC -1。当每个输入文件完成时,ARGV 数组的下一个成员提供下一个输入文件的名称,除非: |
CONVFMT | 将数字转换为字符串的 printf 格式(除了使用 OFMT 特殊变量的输出语句)。缺省值为“%.6g”。 |
ENVIRON | 表示运行 awk 命令的环境的数组。该数组的每个元素在以下格式中:
ENVIRON [ "Environment VariableName" ] = EnvironmentVariableValue 当 awk 命令开始执行时设置这些值,且到执行结束前一直使用该环境,不考虑 ENVIRON 特殊变量的任何修改。 |
FILENAME | 当前输入文件的路径名称。在执行 BEGIN 操作的过程中,FILENAME 的值未定义。在执行 END 操作的过程中,该值是处理的最后一个输入文件的名称。 |
FNR | 当前文件中的当前输入记录的个数。 |
FS | 输入字段分隔符。缺省值是空格。如果输入字段分隔符是空格,则任何数目的语言环境定义的空格可以分隔字段。FS 特殊变量可以有两种附加的值:
|
NF | 当前记录中的字段个数,最大数 99 个。在 BEGIN 操作中,除非先前发出不带 Variable 参数的 getline 函数,否则 NF 特殊变量未定义。在 END 操作中,除非在输入 END 操作之前发出不带 Variable 参数的后续的、重定向的 getline 函数,否则 NF 特殊变量保留它为读取的最后一个记录而具有的值。 |
NR | 当前输入记录的个数。在 BEGIN 操作中,NR 特殊变量的值是 0(零)。在 END 操作中,值是最后处理的记录的编号。 |
OFMT | 在输出语句中将数字转换为字符串的 printf 格式。缺省值为“%.6g”。 |
OFS | 输出字段分隔符(缺省值是空格)。 |
ORS | 输出记录分隔符(缺省值是换行字符)。 |
RLENGTH | 由 match 函数来匹配的字符串的长度。 |
RS | 输入记录分隔符(缺省值是换行字符)。如果 RS 特殊变量为空,则记录以一个或多个空行的序列隔开;第一个空行或最后一个空行在输入的开始和结束都不会产生空记录;换行字符始终是一个字段分隔符,不考虑 FS 特殊变量的值。 |
RSTART | 由 match 函数来匹配的字符串的起始位置,从 1 开始编号。等同于 match 函数的返回值。 |
SUBSEP | 隔开多个下标。缺省值是 \031。 |
该命令返回以下出口值:
0 | 成功完成。 |
>0 | 发生错误。 |
可以通过使用 exit [ Expression ] 条件语句来更改程序中的退出状态。
awk 'length >72' chapter1
这选择 chapter1 文件中长于 72 个字符的每一行,并将这些行写至标准输出,因为未指定 Action。制表符以 1 个字符计数。
awk '/start/,/stop/' chapter1
awk -f sum2.awk chapter1
以下程序 sum2.awk,计算了输入文件 chapter1 中的第二列的数字的总和与平均值:
{ sum += $2 } END { print "Sum: ", sum; print "Average:", sum/NR; }
第一个操作将每行的第二个字段的值添加至变量 sum。当第一次被引用时,所有的变量都初始化为数字值 0(零)。第二个操作前的模式 END 使那些操作在读取了所有输入文件之后才执行。用于计算平均值的 NR 特殊变量是一个指定已经读取的记录的个数的特殊变量。
awk '{ print $2, $1 }' chapter1
awk -f sum3.awk chapter2打印文件 chapter2 的前两个字段(用逗号和/或空格和制表符隔开),然后合计第一列,并打印总和与平均值:
BEGIN {FS = ",|[ \t]+"} {print $1, $2} {s += $1} END {print "sum is",s,"average is", s/NR }
egrep 命令、fgrep 命令、grep 命令、lex 命令、printf 命令、sed 命令。
popen 子例程、printf 子例程、system 子例程。