分类:
2010-01-03 20:37:02
于UNIX的命令行上键入诸如下列格式的指令: ( “$”表Shell命令行上的提示符号)
$awk 'awk程序' 数据文件文件名
则awk会先编译该程序, 然后执行该程序来处理所指定的数据文件.
(上列方式系直接把程序写在UNIX的命令行上)
awk程序的主要结构:
awk程序中主要语法是 Pattern { Actions}, 故常见之awk 程序其型态如下 :
Pattern1 { Actions1 } Pattern2 { Actions2 } ...... Pattern3 { Actions3 }
Pattern 是什么 ?
awk 可接受许多不同型态的 Pattern. 一般常使用 “关系表达式”(Relational expression) 来当成 Pattern.
例如:
x > 34 是一个Pattern, 判断变量 x 与 34 是否存在大于的关系.
x == y 是一个Pattern, 判断变量 x 与变量 y 是否存在等于的关系.
上式中 x >34 , x == y 便是典型的Pattern.
awk 提供 C 语言中常见的关系运算符(Relational Operators) 如
>, <, >=, <=, ==, !=
此外, awk 还提供 ~ (match) 及 !~(not match) 二个关系运算符(注一).
其用法与涵义如下:
若 A 为一字符串, B 为一正则表达式(Regular Expression)
A ~ B 判断 字符串A 中是否 包含 能匹配(match)B表达式的子字符串.
A !~ B 判断 字符串A 中是否 不包含 能匹配(match)B表达式的子字符串.
例如 :
"banana" ~ /an/ 整个是一个Pattern.
因为"banana"中含有可以匹配 /an/ 的子字符串, 故此关系式成立(true),整个Pattern的值也是true.
相关细节请参考 awk 之Patterns, awk 之Regular Expression
(注一:) 有少数awk论著, 把 ~, !~ 当成另一类的 Operator,并不视为一种 Relational Operator. 这里将这两个运算符当成一种 Relational Operator.
Actions 是什么?
Actions 是由许多awk指令构成. 而awk的指令与 C 语言中的指令十分类似.
例如 :
awk的 I/O指令 : print, printf( ), getline…
awk的 流程控制指令 : if(…){..} else{..}, while(…){…}…
(请参考 awk 之 “Actions” )
awk 如何处理 Pattern { Actions } ?
awk 会先判断(Evaluate) 该 Pattern 的值, 若 Pattern 判断后的值为true (或不为0的数字,或不是空的字符串), 则 awk将执行该 Pattern 所对应的 Actions.反之, 若 Pattern 之值不为 true, 则awk将不执行该 Pattern所对应的 Actions.
例如 : 若awk程序中有下列两指令
50 > 23 {print “Hello! The word!!” }
“banana” ~ /123/ { print “Good morning !” }
awk会先判断 50 >23 是否成立. 因为该式成立, 所以awk将印出”Hello! The word!!”. 而另一 Pattern 为 “banana” ~/123/, 因为”banana” 内未含有任何子字符串可 match /123/, 该 Pattern 之值为false, 故awk将不会印出 “Good morning !”
awk 如何处理{ Actions } 的语法?(缺少Pattern部分)
有时语法 Pattern { Actions }中, Pattern 部分被省略,只剩 {Actions}.这种情形表示 “无条件执行这个 Actions”.
awk 的字段变量
awk 所内建的字段变量及其涵意如下 :
$0 一字符串, 其内容为目前 awk 所读入的数据行. $1 $0上第一个字段的数据. $2 $0上第二个字段的数据. ... 其余类推
读入数据行时, awk如何更新(update)这些内建的字段变量?
当 awk 从数据文件中读取一个数据行时, awk 会使用内建变量$0 予以记录.每当 $0 被改动时 (例如 : 读入新的数据行 或 自行变更 $0,…) awk 会立刻重新分析 $0 的字段情况, 并将 $0 上各字段的数据用 $1, $2, ..予以记录.
awk的内建变量(Built-in Variables)
awk 提供了许多内建变量, 使用者于程序中可使用这些变量来取得相关信息.常见的内建变量有 :
NF (Number of Fields) 为一整数, 其值表$0上所存在的字段数目. NR (Number of Records) 为一整数, 其值表awk已读入的数据行数目. FILENAMEawk 正在处理的数据文件文件名.
例如 : awk 从资料文件 emp.dat 中读入第一笔数据行
“A125 Jenny 100 210″ 之后, 程序中:
$0 之值将是 “A125 Jenny 100 210″
$1 之值为 “A125″
$2 之值为 “Jenny”
$3 之值为 100
$4 之值为 210
$NF 之值为 4
$NR 之值为 1
$FILENAME 之值为 “emp.dat”
awk的工作流程 :
执行awk时, 它会反复进行下列四步骤.
awk会自动重复进行上述4个步骤, 使用者不须于程序中编写这个循环 (Loop).
打印文件中指定的字段数据并加以计算
awk 处理数据时, 它会自动从数据文件中一次读取一笔记录, 并会将该数据切分成一个个的字段; 程序中可使用 $1, $2,… 直接取得各个字段的内容. 这个特色让使用者易于用 awk 编写 reformatter 来改变量据格式.
[ 范例 :] 以文件 emp.dat 为例, 计算每人应发工资并打印报表.
[ 分析 :] awk 会自行一次读入一列数据, 故程序中仅需告诉awk 如何处理所读入的数据行.
执行如下命令 : ( $ 表UNIX命令行上的提示符 )
$ awk '{ print $2, $3 * $4 }' emp.dat
执行结果如下 :
屏幕出现 :
Jenny 21000 Dan 23650 Max 27170 John 27500 Linda 19950
[ 说明 :]
UNIX命令行上, 执行awk的语法为:
$awk 'awk程序' 欲处理的资料文件文件名
本范例中的 程序部分 为 {print $2, $3 * $4}.
把程序置于命令行时, 程序之前后须以 ‘ 括住.
emp.dat 为指定给该程序处理的数据文件文件名.
本程序中使用 : Pattern { Actions } 语法.
Pattern 部分被省略, 表无任何限制条件. 故awk读入每笔数据行后都将无条件执行这个 Actions.
print为awk所提供的输出指令, 会将数据输出到stdout(屏幕).
print 的参数间彼此以 “,” (逗号) 隔开, 印出数据时彼此间会以空白隔开. (参考 awk 之内建变量”OFS”)
将上述的 程序部分 储存于文件 pay1.awk 中. 执行命令时再指定awk程序文件 之文件名. 这是执行awk的另一种方式, 特别适用于程序较大的情况, 其语法如下:
$ awk -f awk程序文件名 数据文件文件名
故执行下列两命令,将产生同样的结果.
$ awk -f pay1.awk emp.dat $ awk '{ print $2, $3 * $4 }' emp.dat
读者可使用 “-f” 参数,让awk主程序使用“其它仅含 awk函数 的文件中的函数 ”
其语法如下:
$ awk -f awk主程序文件名 -f awk函数文件名 数据文件文件名
awk中也提供与 C 语言中类似用法的 printf() 函数. 使用该函数可进一步控制数据的输出格式.
编辑另一个awk程序如下, 并取名为 pay2.awk
{ printf("%6s Work hours: %3d Pay: %5d\n", $2,$3, $3* $4) }
执行下列命令
$awk -f pay2.awk emp.dat
执行结果屏幕出现:
Jenny Work hours: 100 Pay: 21000 Dan Work hours: 110 Pay: 23650 Max Work hours: 130 Pay: 27170 John Work hours: 125 Pay: 27500 Linda Work hours: 95 Pay: 19950