当前位置:首页 > awk 命令详解教程
\之后, 程序中: $0 之值将是 \ $1 之值为 \ $2 之值为 \ $3 之值为 100 $4 之值为 210 $NF 之值为 4 $NR 之值为 1
$FILENAME 之值为 \
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 的参数间彼此以 \逗号) 隔开, 印出数据时彼此间会以空白隔开. (参考 附录 D 内建变量OFS)
将上述的 程序部分 储存于文件 pay1.awk 中. 执行命令时再指定awk程序文件 之文件名. 这是执行awk的另一种方式, 特别适用于程序较大的情况, 其语法如下:
$ awk -f awk程序文件名 数据文件文件名
故执行下列两命令,将产生同样的结果.
$ awk -f pay1.awk emp.dat $ awk '{ print $2, $3 * $4 }' emp.dat
读者可使用 \参数,让awk主程序使用“其它仅含 awk函数 的文件中的函数 ”
其语法如下:
$ awk -f awk主程序文件名 -f awk函数文件名 数据文件文件名
(有关 awk 中函数的声明与使用于 7.4 中说明)
awk中也提供与 C 语言中类似用法的 printf() 函数. 使用该函数可进一步控制数据的输出格式.
编辑另一个awk程序如下, 并取名为 pay2.awk
{ printf(\
执行下列命令
$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
4. 选择符合指定条件的记录
Pattern { Action }为awk中最主要的语法. 若某Pattern之值为真则执行它后方的 Action. awk中常使用\关系表达式\来当成 Pattern. awk 中除了>, <, ==, != ,...等关系运算符( Relational Operators )外,另外提供 ~(match),!~(Not Match) 二个关系运算符. 利用这两个运算符, 可判断某字符串
是否包含能匹配所指定正则表达式的子字符串. 由于这些特性, 很容易使用awk来编写需要字符串比对, 判断的程序. [ 范例 :] 承上例,
组装部门员工调薪5%,(组装部门员工之ID以\开头) 所有员工最后之薪资率若仍低于100, 则以100计. 编写awk程序打印新的员工薪资率报表.
[分析 ] : 这个程序须先判断所读入的数据行是否合于指定条件, 再进行某些动作.awk中 Pattern { Actions } 的语法已涵盖这种 \条件) { 动作} \的架构. 编写如下之程序, 并取名 adjust1.awk
$1 ~ /^A.*/ { $3 *= 1.05 } $3<100 { $3 = 100 } { printf(\
执行下列命令 :
$awk -f adjust1.awk emp.dat
结果如下 : 屏幕出现 :
A125 Jenny 105 A341 Dan 115 P158 Max 130 P148 John 125 A123 Linda 100
说 明 :
awk的工作程序是: 从数据文件中每次读入一个数据行, 依序执行完程序中所有的 Pattern{ Action }指令: $1~/^A.*/ { $3 *= 1.05 } $3 < 100 { $3 = 100 }
{printf(\
再从数据文件中读进下一笔记录继续进行处理.
第一个 Pattern { Action }是: $1 ~ /^A.*/ { $3 *= 1.05 }
$1 ~ /^A.*/ 是一个Pattern, 用来判断该笔数据行的第一栏是否包含以\开头的子字符串. 其中 /^A.*/ 是一个Regular Expression, 用以表示任何以\开头的字符串. (有关 Regular Expression 之用法 参考 附录 E ). Actions 部分为 $3 *= 1.05
$3 *= 1.05 与 $3 = $3 * 1.05 意义相同. 运算子\之用法则与 C 语言中一样. 此后与 C 语言中用法相同的运算子或语法将不予赘述.
第二个 Pattern { Actions } 是: $3 <100 {$3 = 100 } 若第三栏的数据内容(表薪资率)小于100, 则调整为100.
第三个 Pattern { Actions } 是: {printf(\省略了Pattern(无条件执行Actions), 故所有数据行调整后的数据都将被印出.
5. awk 中数组
awk程序中允许使用字符串当做数组的下标(index). 利用这个特色十分有助于资料统计工作.(使用字符串当下标的数组称为Associative Array)
首先建立一个数据文件, 并取名为 reg.dat. 此为一学生注册的资料文件; 第一栏为学生姓名, 其后为该生所修课程.
Mary O.S. Arch. Discrete Steve D.S. Algorithm Arch. Wang Discrete Graphics O.S. Lisa Graphics A.I. Lily Discrete Algorithm
awk中数组的特性
使用字符串当数组的下标(index).
使用数组前不须宣告数组名及其大小.
例如: 希望用数组来记录 reg.dat 中各门课程的修课人数. 这情况,有二项信息必须储存:
(a) 课程名称, 如: \共有哪些课程事先并不明确. (b)各课程的修课人数. 如: 有几个人修\
在awk中只要用一个数组就可同时记录上列信息. 其方法如下: 使用一个数组 Number[ ] :
以课程名称当 Number[ ] 的下标.
以 Number[ ] 中不同下标所对映的元素代表修课人数. 例如:
有2个学生修 \则以 Number[\表之.
若修\的人数增加一人,则 Number[\或 Number[\
如何取出数组中储存的信息
以 C 语言为例, 声明 int Arr[100]; 之后, 若想得知 Arr[ ]中所储存的数据, 只须用一个循环, 如 :
for(i=0; i<100; i++) printf(\ 即可. 上式中:
数组 Arr[ ] 的下标 : 0, 1, 2,..., 99
数组 Arr[ ] 中各下标所对应的值 : Arr[0], Arr[1],...Arr[99]
但 awk 中使用数组并不须事先宣告. 以刚才使用的 Number[ ] 而言, 程序执行前, 并不知将来有哪些课程名称可能被当成 Number[ ] 的下标.
awk 提供了一个指令, 藉由该指令awk会自动找寻数组中使用过的所有下标. 以 Number[ ] 为例, awk将会找到 \
使用该指令时, 须指定所要找寻的数组, 及一个变量. awk会使用该的变量来记录从数组中找到的每一个下标. 例如
for(course in Number){....}
指定用 course 来记录 awk 从Number[ ] 中所找到的下标. awk每找到一个下标时, 就用course记录该下标之值且执行{....}中之指令. 藉由这个方式便可取出数组中储存的信息. (详见下例)
[ 范例 : ] 统计各科修课人数,并印出结果. 建立如下程序,并取名为 course.awk:
{ for( i=2; i <= NF; i++) Number[$i]++ }
END{for(course in Number) printf(\
共分享92篇相关文档