Chinaunix首页 | 论坛 | 博客
  • 博客访问: 514384
  • 博文数量: 119
  • 博客积分: 5054
  • 博客等级: 大校
  • 技术积分: 1305
  • 用 户 组: 普通用户
  • 注册时间: 2010-01-03 13:13
文章分类

全部博文(119)

文章存档

2011年(4)

2010年(115)

我的朋友

分类:

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时, 它会反复进行下列四步骤.

  1. 自动从指定的数据文件中读取一个数据行.
  2. 自动更新(Update)相关的内建变量之值. 如 : NF, NR, $0…
  3. 依次执行程序中 所有 的 Pattern { Actions } 指令.
  4. 当执行完程序中所有 Pattern { Actions } 时, 若数据文件中还有未读取的数据, 则反复执行步骤1到步骤4.

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
阅读(750) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~