第一章 关于UNIX Shell的介绍
1. 定义
shell 是一种特殊的程序,被用作用户与内核(kernel)的UNIX操作系统核心
通讯。常见的shell有C shell、B shell 和 Korn shell(B shell的超集)。
2. shell 主要功能
.. 解释交互运行时,在命令行提示下敲入的命令
.. 制订用户环境,通常在shell初始化文件中作这种工作。例如:设置终
端键及窗口特征;设置搜索路径、权限、提示等
.. shell 可以用作解释编程语言。Shell程序也叫命令表,由再文件中列出
的命令组成。
3. 主要shell命令:
who mv rm wc ls cat date at
lpr rsh more awk pwd bc vi finger w
pg find cc cp dd grep ksh sh
ps sed cal lp
第2章 UNIX工具箱
1.正则表达式
一个正则表达式就是用来在一次搜索中匹配相同字符的一个字符模式。在大
多数程序中,把一个正则表达式封装在正斜杠(/)里。
2.正则表达式元字符
元字符
功能
实例
解释
^
行开头定位
/^love/
与所有love开头的行匹配
$
行末尾定位
/love$/
与所有love结尾的行匹配
.
匹配单个字符
/l..e/
与包含一个l,后跟两个字符,然后跟一个e的行相匹配 *
跟前驱的0个或多
个字符相匹配
/ *love/
跟0个或多个空格后面的
love模式的行相匹配
[]
与其中的一个相匹
配
/[Ll]ove/
与包含love或者Love的行
匹配
[x-z]
与集中一个范围内
的一个字符相匹配
/[A-Z]ove/
与后面跟ove的从A到Z的
字相匹配
[^]
与不在集里的字符
匹配
/[^A-Z]ove/
不包括A到Z,后面跟ove
的字相匹配
/
给一个元字符转移
/love/./
匹配行包括love,跟一个句
点
许多用RE元字符的UNIX程序支持的附加元字符(vi 和 grep支持)
/<
词开头定位
//<love/
匹配行包含用love开头的
词
/>;
词结尾定位
/love/>;/
匹配行包含love结尾的词
/(../)
标志与以后用的字
符相匹配
/(love/)able/ler/
Able可达9个标志,模式最
左边用第一个标志开始。例
如,模式love保存作标志
l,以后引用作/l;在这个例
子中,搜索模式包括后面跟
lover的lovable
x/{m/}
x/{m,/}
x/{m,n/}
字符x重复m次
至少m次
m到n次
O/{5,10/}
如果行包含5—10个连续的
o则匹配
表(2.1)
3.举例
查找文件中的含有love的词:
% vi picnic
I had a lovely time on our little picnic. Lovers were all around
us, oh love
:/love/
4.组合正则表达式元字符
文件内容:(数字是行号,竖线标明行的左右边界,不属于文件内容。这个文
件我写在shell/exam/exam_2.9中)
1 |Christian Scott lives here and will put on a Christmas party.|
2 |There are around 30 to 35 people invited.|
3 |They are: |
4 | Tom|
5 |Dan|
6 | Rhonda Savage|
7 |Nicky and Kimerly.|
8 |Steve, Suzanne, Ginger and Larry.|
组合举例:
.. /^[A-Z]..$/
搜索行以A至Z的一个字母开头,然后跟两个任意字母,然后跟一
个换行符的行。将找到第5行。
.. /^[A-Z][a-z]*3[0-5]/
搜索以一个大写字母开头,后跟0个或多个小写字母,再跟数字3,
再跟0—5之间的一个数字。
.. *[A-Z][a-z][a-z]$/
搜索以0个或多个空格开头,跟一个大写字母,两个小写字母和一
个换车符。将找到第4行的TOM(整行匹配)和第5行。注意,*前
面有一个空格。
.. /^[A-Za-z]*[^,][A-Za-z]*$/
将查找以0个或多个大写或小写字母开头,不跟逗号,然后跟0个
或多个大写或小写字母,然后跟一个换车符。将找到第5行。书中
解释有误。
5.更多的正则表达式元字符
这里讨论的元字符不一定可以移植到所有的正则表达式中,但一般可以用在
vi、sed和grep中。
% vi textfile
Patty won fourth place in the 50 yard dash square and fair.
Occurences like this are rare.
Haha, what you want is just fourth.
~
~
://<fourth/>;/
将查找词fourth
第3章 grep家族
1.grep的含义是“全局搜索正则表达式(RE)并打印该行”
2.grep支持的正则表达式
与在文件中搜索基本一样。可以参考表2.1。
3.grep 的选项
选项
功能
-b
在各行之前放置它发现的块号。有时在根据上下文定位磁盘字块时有用
-c
显示匹配行数而不是内容
-h
不显示文件名
-I
在座比较时忽略字母大小写
-n
文件中每行之前给出它的相关行号
-s
无声操作。即除了错误消息外不做任何显示。用于检查退出状态
-v
把搜索翻转为只显示不匹配的行
-w
把表达式当作一个次来搜索,相当于用/<和/>;括起来
表3.1
4.grep命令的退出状态
如果grep操作成功,则状态是0,如果模式没找到,状态是1,如果文件没
找到,状态是2。如果操作被取消,则状态是130。查看状态的方法:在csh
中用echo $status。在sh和ksh中用echo $? 。例如
$ echo $?
0
5.带正则表达式的grep举例:
用于这些例子的文件叫datafile,位于chap03目录。内容如下:
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
1) grep NW datafile
解释:打印datafile中包含NW的行
2) grep NW d*
解释:打印所有以d开头的文件中含有NW的文件。
3) grep '^n' datafile
解释:打印文件datafile中所有以字母n开头的行
4) grep TB Savage datafile
解释:在Savage和datafile文件中查找有TB的行
5) grep 'TB Savage' datafile
解释:在datafile文件中查找含有TB Savage的行并打印。这个例子在
书中有误。
6) grep '^[we]' datafile
打印datafile中以w或者e开头的行
7) grep 'ss* ' datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
解释:打印所有包含一个s并跟0个或者多个s,然后跟一个空格的行
6.用管道的grep
grep 可以从管道得到输入。
% ls –l
drwxr-xr-x 6 oracle dba 512 4月 3 21:49 chap10
drwxr-xr-x 2 oracle dba 512 4月 10 22:23 exam
-rwxr--r-- 1 oracle dba 1842 4月 3 21:51 readme.txt
-rwxr--r-- 1 oracle dba 1801 4月 3 21:51 unix_readme.txt
% ls –l | grep '^d'
drwxr-xr-x 6 oracle dba 512 4月 3 21:49 chap10
drwxr-xr-x 2 oracle dba 512 4月 10 22:23 exam
% ls -l |grep '^[^d]'
-rwxr--r-- 1 oracle dba 1842 4月 3 21:51 readme.txt
-rwxr--r-- 1 oracle dba 1801 4月 3 21:51 unix_readme.txt
7.带选项的grep举例:
grep –c ‘west’ datafile
3
解释计算datafile中含有west的总数。
8.egrep (扩展的grep)
egrep可以使用额外的正则表达式,如下表。
元字符
功能
例子
解释
+
匹配一个或多个前驱字符
'[a-z]+ove'
匹配一个或多个小写
字母,后跟ove
?
匹配0个或者1个前驱字
符
'lo?ve'
将找到love或love
a|b
匹配a或者b
'love|hate'
与love或hate匹配
()
组字符
'lov(ely|able)
与lovely或lovable
匹配
表3.2
9.egrep 举例:
egrep '2/.?[0-9]' datafile
解释:打印所有这样的行:它包含一个2,后跟0个或者一个句号,然后跟
一个数字。
10. fgrep
fgrep 把所有的元字符都当作字符本身,只代表自己。
11. UNIX 工具试验参考答案(内容参考datebook)
.. 打印包含San的行
grep 'San' datebook
.. 打印所有以J开头的人名所在的行
grep '^J' datebook
.. 打印以700结尾的行
grep '700$' datebook
.. 打印所有不包含834的行
grep -v '834' datebook
.. 打印出生在12月(December)的行
grep '/12' datebook
.. 打印工资是6位数的行,并给出行号
grep -n '[0-9]/{6,/}$' datebook
第4章 流编辑器(sed)
1. sed 命令简介
sed 是流线型、非交互式编辑器。它允许你执行与vi 和ex编辑器里一样的
编辑任务。Sed 程序不是与编辑器交互式工作的,而是让你在命令行里敲入编辑
的命令,给文件命名,然后在屏幕上查看命令输出结果。
2. sed 如何工作
sed 编辑器按一次处理一行的方式来处理文件,并把输出送到屏幕上。
3. sed 可以用寻址的方式来决定想要编辑哪一行。
4. sed 命令和选项
命令
功能
a/
在当前行上添加一个文本行或者多个文本行
c/
用新闻本改变(取代)当前行里的文本
d
删除行
i/
在当前行之前插入文本
h
把模式空间内容复制到一个固定缓存
H
把模式空间内容添加到一个固定缓存
g
得到固定缓存里所有的禀复制到模式缓存,重写其内容
G
得到固定缓存的内容并复制到模式缓存,添加到里面
I
列出不打印的字符
p
打印行
n
读下一输入行,并开始用下一个命令处理换行符,而不是用第一个
命令
q
结束或退出sed
r
从一个文件读如行
!
把命令应用到除了选出的行以外的其他所有行
s
把一个字串替换成另一个
替换标志
g
在一行上进行全局替换
p
打印行
w
把行写到一个文件中
x
用模式空间的内容交换固定缓存的内容
y
把一个字符转换成另一个(不能和整则表达式元字符一起使用)
5. sed 元字符
基本上,grep和vi使用的元字符都可以用在sed中。具体可参照第二章。
下表列出了一些特别的sed 元字符:
元字符
功能
例子
解释
&
保存搜索串以便可
以记在替换串里
s/love/**&**/
&号代表搜索串。串love将被星
号包围的自身所替代;即love
变成**love**
6. sed 的实例(使用datafile)
1>; 打印:p命令
sed '/north/p' datafile
默认输出所有行,找到north的行重复打印
sed –n '/north/p' datafile
禁止默认输出,只打印找到north的行
2>; 删除:d命令
sed '3d' datafile
删除第三行,其余行输出到屏幕
sed '3,$d' datafile
从第3行到最后一行都删除,将剩余部分输出到屏幕
sed '/north/d' datafile
将含有north的行删除,其余输出到屏幕
3>; 替换:s命令
sed 's/west/north/g' datafile
解释:找到datafile中的所有west并替换成north,将替换后的内容输
出到屏幕。
sed 's/[0-9][0-9]$/&.5/' datafile
解释:在替代串里的&字符代表在搜索串中真正找到的。每个以两个数字
结尾的行都被它自己取代,且要在后面加上.5
sed -n 's/Hemenway/Jones/gp' datafile
解释:所有的Hemenway所在的位置都用Jones来取代,而且只有改变的
行被打印。-n与p命令选项相结合来禁止默认输出。g代表全局替换
sed -n 's//(Mar/)got//1ianne/p' datafile
解释:模式Mar被封装在括弧里且在一个专用寄存器里存为标记1。在替
换串里它将被引用做/1。然后用Marianne替代Margot。
sed 's#3#88#g' datafile
s命令后面的字符是搜索串和替换串之间的分界符。默认的分界符是一个
正斜杠,但也可以改变(只有使用s命令时)。无论s命令后面跟什么字
符,它都是新的串分界符。当搜索包含一个正斜杠的模式,如路径或生
日时,这种技巧可能有用
4>; 被选中的行的范围:逗号
sed -n '/west/,/east/p' datafile
打印在west和east之间的模式范围内所有行。如果west出现在east
之后,则打印从west到下一个east或者到文件末尾的行,无论哪种情
况先出现都可以。
sed '/west/,/east/s/$/**VACA**/' datafile
解释:对于在模式west到east范围内的行,行末尾将用**VACA**来取代。
5>; 多次编辑 -e 选项
sed -e '1,3d' -e 's/Hemenway/Jones/' datafile
-e选项允许多次编辑。不同的编辑顺序可能导致不同的结果。例如,如
果两个命令都执行了替换,第一次替换可能影响第二次替换。
6>; 从文件中读取:r命令
sed '/Suan/r newfile' datafile
解释:r命令从newfile中读取内容,将内容输出到Suan的后面。如果
datafile中Suan出现的次数不只一次,则分别放到Suan的后面。
7>; 写入文件:w命令
sed -n '/north/w newfile' datafile
解释:w命令把指定的行写入到一个文件。本例中所有的包含north的行
写入到newfile中。等同于sed -n '/north/p' datafile >;newfile
8>; 添加:a命令
$ sed '/north/a/
>; ---->;THE NORTH SALES DISTRICT HAS MOVED<-----' datafile
northwest NW Charles Main 3.0 .98 3 34
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
north NO Margot Weber 4.5 .89 5 9
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
central CT Ann Stephens 5.7 .94 5 13
解释:红颜色的内容是要输入的内容。a/命令后面跟要添加的内容。奇怪的是a/后
面必须另起一行,在输入要添加的内容,否则会提示命令错乱,真是搞不懂。
9>; 插入:i命令
$ sed '/north/i/
>; ---->;THE NORTH SALES DISTRICT HAS MOVED<-----' datafile
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
northeast NE AM Main Jr. 5.1 .94 3 13
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
解释:在符合模式的行前面插入内容。其余和a/命令相同。
10>;下一个:n命令
$ sed '/eastern/{n;s/AM/Archie/;}' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE Archie Main Jr. 5.1 .94 3 13
……
解释:如果在某一行里模式eastern被匹配,n命令使sed区的下一行,
用该行带换模式空间,用Archie替换AM,打印并继续。
11>;变换:y 命令
sed '1,3y/abcdefghijklmnopqrst/ABCDEFGHIJKLMNOPQRST/' datafile
解释将对应字母进行转换。
12>;退出:q 命令
sed '5q' datafile
解释:在打印了5行之后,用q命令退出sed程序。
13>;保存和取得:h和G命令
$ sed -e '/southeast/h' -e '$G' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
southeast SE Patricia Hemenway 4.0 .7 4 17
解释:当sed 处理文件时,每行都存在模式空间(pattern space)的临时缓存中。
除非行被禁止打印或删除,否则行将在处理完后被打印到屏幕,然后请模式空间并把
下一输入行保存在那里等待处理。在这个例子中,在找到模式之后,把它放在模式
空间里,而且h命令复制它并把它存到另一个叫做保存缓存(holding buffer)中。
第二个sed指令里,当读入最后一行($)时,G命令告诉sed从包存缓存中取得该行
并放回模式空间缓存,添加到当前存在那里的行中。本例子就是最后一行。
$ sed -e '/WE/{h;d;}' -e '/CT/G' datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
western WE Sharon Gray 5.3 .97 5 23
解释:第一个命令h将找到了WE的行放到保存缓存中,然后删除该行;第二个命令
/CT/G就是在找到了CT的行的后面加入保存缓存的内容。
14>;G和g的区别
G命令在符合的条件行后面添加保存缓存中的内容;g命令用保存缓存中
的内容覆盖符合条件的行。
15>;sed 命令的花括号{}的作用
花括号{}中可以放入多个命令,每个命令后面要用分号;。
16>;保存和交换:h 和 x命令。
$ sed -e '/Patricia/h' -e '/Margot/x' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
southeast SE Patricia Hemenway 4.0 .7 4 17
central CT Ann Stephens 5.7 .94 5 13
解释:x命令将找到的行用保存缓存中的内容替换。
7. 用sed来编写命令表
sed 命令表(script)是文件里的一个sed命令列表。用-f选项来引用一
个命令表文件。编辑sed命令表有特殊要求:命令末尾不能有任何为岁的空
白符或者文本。如果命令不是自成一行,就必须用分号结束。在源代码chap4
目录下有两个编辑好的命令表文件(sedding1和sedding2)可以参考。下面是
使用sed命令表的例子。
$ sed -f sedding1 datafile
EMPLOYEE DATABASE
---------------------
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
Lewis is the TOP Salesperson for April!!
Lewis is moving to the southern district next month.
CONGRATULATIONS!
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
*******************
MARGOT HAS RETIRED
*******************
8. Sed练习参考答案
练习内容参考databook文件
1〉 把Jon改成Jonathan
sed 's/Jon/Jonathan/' datebook
2〉 删除头3行
sed '1,3d' datebook
3〉 打印5—10行
sed -n '5,10p' datebook
4〉 删除包含Lane的行
sed '/Lane/d' datebook
5〉 打印所有生日是在Noverber到December之间的行
sed -n '/:1[12]///p' datebook
6〉 把三个星添加到以Fred开头的行尾
sed '/^Fred/s/$/***/' datebook
7〉 用JOSE HAS RETIRED取代包含Jose的行
sed 's/^Jose[0-9]*[a-z]*[A-Z]* *.*$/JOSE HAS LEFT/' datebook
8〉 把Popeye的生日改成11/14/46
sed '/Popeye/s/:[0-9]*[0-9]*//[0-9]*[0-9]*//[0-9]*[0-9]*/:11//14//46/' datebook
9〉 删除所有空白行
sed '/^$/d' datebook
10〉 写一个sed命令表,将:
a. 在第1行之前插入标题PERSONNEL FILE
b. 删除以500结尾的工资
c. 打印文件内容,把姓和名颠倒
d. 在文件末尾添加THE END
答案放在chap04/a10文件中,内容如下:
# My first sed script by Wangzhh.
1i/
PERSONNEL FILE
/500/d
s//([A-Z][a-z]*/) /([A-Z][a-z]*/)://2 /1:/
$a/
THE END
第5章 awk 实用程序:awk作为一种UNIX工具
1. awk 简介
awk 是用来操作数据和产生报表的一种编程语言。数据可能来自标准输入、
一个或者多个文件或者是一个进程的输出。awk 可以用在命令行里用于简单
操作,或者可以为了较大的应用而写到程序中。常见的awk命令有awk、nawk
等。awk从第1行到最后一行逐行扫描文件(或输入),并执行选定的操作(封
装在花括号里)。本文章所有的例子使用的文件未经说明都在chap05目录下。
2. awk的格式
awk程序由awk命令,封装在引号里(或在一个文件里)的程序指令,和输
入文件组成。如果没有指定一个输入文件,则输入来自标准输入(stin)键盘。
employees文件中的内容:
$ cat employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
1〉从文件输入
$ awk '/Mary/' employees
解释:打印employees文件中含有Mary的行
$ awk '{print $1}' employees
Tom
Mary
Sally
Billy
解释:打印文件employees中的第一个域。域的分隔符是空格。
nawk '/Sally/{print $1,$2}' employees
解释:只有找到了Sally的行才打印第一个域和第二个域。
2〉管道输入
$ df -k|awk '$4>;1024000'
解释:报告剩余空间大于1024000k的盘。
3. 格式化输出
1〉print函数
例子1:
$ date
2005年04月30日 星期六 19时29分25秒 CST
$ date|awk '{print "Date:" $1 "/nTime:" $3}'
Date:2005年04月30日
Time:19时34分24秒
注意,用date命令查看时间格式。不同的语言可能格式也不一样,因此
awk也要随之而变。/n是转义序列,表示换行符。常见转义序列如下表:
转义序列
含义
/b
退格
/f
换页
/n
换行
/r
回车
/t
跳格
/047
八进制值47,一个单引号
/c
C代表任意其它字符,例如/''
表5.1 转义序列
例子2:
$ nawk '/Sally/{print "/t/tHave a nice day, "$1,$2 "/!"}' employees
Have a nice day, Sally Chang!
解释:如果包含模式Sally,则print函数打印两个跳格,串Have a nice
day,第一个域和第二个域,然后跟叹号。
OFMT变量:当打印数字时,如果使用print函数,想控制精度时,可以
用OFMT变量。默认设置是“%.6g”,也就是打印精度到小数点后6位。下
面的例子可以改变精度。
$ nawk 'BEGIN{OFMT="%.2f"; print 1.23456789,12E-2}'
1.23 0.12
2〉printf函数
printf函数提供了强大的格式化输出功能,如果对c比较熟悉,就不会
感觉太陌生。
转换字符
定义
c
字符
s
串
d
十进制数
ld
长十进制数
u
无符号十进制数
lu
无符号长十进制数
x
十六进制数
lx
长十六进制数
o
八进制数
lo
长八进制数
e
以科学技术发记的符点数
f
浮点数
g
从e或f转换中选择一种占用空间最少的记符点数
表5.2 printf的转换字符
字符
定义
-
左对齐修饰符
#
整数在用八进制显示前面有个0;整数在用十六进制显示时
前面有个0x
+
对于用d、e、f和g的转换,带一个数字符号+或-显示整数
0
显示的值用0补而不是用空格
表5.3修饰符
格式符
功能
假设x=’A’ y=15 z=2.3 $1=Bob Smith
%c
打印一个单ASCII字符
$ printf "The character is %c/n" $x
The character is A
%d
打印一个十进制数
$ printf "The boy is %d years old/n" $y
The boy is 15 years old
%e
打印用科学计数法记的一个数
$ printf "z is %e/n" $z
z is 2.300000e+00
%f
打印一个符点数
$ printf "z is %f/n" $z
z is 2.300000
%o
打印一个数的八进制值
$ printf "y is %o/n" $y
y is 17
%s
打印一个字符串
$ printf "The name of the culprit is %s/n" $1
The name of the culprit is Bob Smith
%x
打印一个数的十六进制值
$ printf "y is %x/n" $y
y is f
表5.4 printf格式说明符
例子:
$ echo UNIX |awk '{printf "|%-15s|/n",$1}'
|UNIX |
解释:echo命令输出从管道中送给awk。格式说明符说明将会打印一个
占15个空格,左对齐,封装在竖杠里而且有换行的串。
$ awk '{printf "The name is %-15s ID is %8d/n",$1,$3}' employees
The name is Tom ID is 4424
The name is Mary ID is 5346
The name is Sally ID is 1654
The name is Billy ID is 1683
4. 在一个文件里的awk命令
如果awk命令放在文件里,就使用-f选项和awk文件名结合使用。处理过程:
把一条记录读到awk的缓存里而且对该记录测试并执行awk文件里的每个命
令。在awk完成对第一条记录的操作后,删除该记录并把下一条记录读入缓
存,依此类推。如果操作不受模式控制,则默认行为是打印整个记录。
例子:
$ cat employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
$ cat awkfile
/^Mary/{print "Hello Mary!"}
{print $1, $2, $3}
$ nawk -f awkfile employees
Tom Jones 4424
Hello Mary!
Mary Adams 5346
Sally Chang 1654
Billy Black 1683
5. 记录和域
1〉记录:awk不把输入数据看作一个无穷的字符串,而是把它看作一种格式
或结构。默认情况下把每行叫做一个记录(record),并以一个换行符终
止。输入和输出的记录分隔符默认是回车符,保存在内置awk变量ORS
和RS中。ORS和RS可以改变,但是方式有限。
例子:
$ nawk '{print $0}' employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
解释:变量$0保存当前记录,这条命令相当于nawk '{print}' employees
例子:
$ awk '{print NR,$0}' employees
1 Tom Jones 4424 5/12/66 543354
2 Mary Adams 5346 11/4/63 28765
3 Sally Chang 1654 7/22/54 650000
4 Billy Black 1683 9/23/44 336500
解释:NR代表行号。
2〉域
类似表中的字段,是指记录中的一个词条。默认域分隔符是空白区域,
也就是空格或制表符(TAB)。Awk中用NF来记录每条记录的域数量。
3〉域分隔符
输入域分隔符:awk的内置变量FS保存输入域分隔符的值。当时用FS
的默认值时,awk用空格或制表符分隔域,删除前导空白区和制表符。FS
可以改变,可以在BEGIN语句中改变,也可以在命令中改变。要想在命
令中改变需要用-F选项。
举例:
$ cat employees2
Tom Jones:4424:5/12/66:543354
Mary Adams:5346:11/4/63:28765
Sally Chang:1654:7/22/54:650000
Billy Black:1683:9/23/44:336500
$ awk '{print $1,$2}' employees2
Tom Jones:4424:5/12/66:543354
Mary Adams:5346:11/4/63:28765
Sally Chang:1654:7/22/54:650000
Billy Black:1683:9/23/44:336500
$ awk -F: '{print $1,$2}' employees2
Tom Jones 4424
Mary Adams 5346
Sally Chang 1654
Billy Black 1683
举例2:多个域分隔符。如果使用多个域分隔符,要将其封装在方括号里。
$ nawk -F'[ :/t]' '{print $1,$2,$3}' employees2
Tom Jones 4424
Mary Adams 5346
Sally Chang 1654
Billy Black 1683
解释:把空格、制表符、冒号当成输入域分隔符。
输出域分隔符:默认的输出域分隔符用逗号来分隔,被分隔的域之间打
印一个空格,如果域之间没有逗号,则打印时各域将挤在一起。
6.模式和操作
awk 模式(patterns)控制awk将对一行输入作什么样的操作。一个模式包括
一个正则表达式,一个产生正确或者错误条件的表达式,或者它们的组合。
默认操作时打印模式中符合表达式条件的各行。当读入一个模式时,有一条
隐含的if语句。如果if语句是隐含的,周围可以没有花括号。
例子:
$ awk '$3<4000' employees
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
解释:如果第3个域小于4000,则打印该域。
操作:操作(actions)是封装在花括号里且由分号分隔的语句。如果一个模式
在一个操作之前,则该模式规定了何时执行该操作。
举例:
$ awk '/Tom/{print "Hello there," $1}' employees
Hello there,Tom
解释:如果记录中包含Tom,则打印Hello there,Tom
7.正则表达式
一个正则表达式对awk来说是一个由封装在正斜杠里的字符组成的模式。Awk
支持的正则表达式与egrep基本一样,可以参考表3.1和表3.2。
举例:
$ nawk '/^Mary/' employees
Mary Adams 5346 11/4/63 28765
解释:显示employees文件中以Mary开头的行
$ nawk '/^[A-Z][a-z]* /' employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
解释:显示行开头是一个大写字母,然后跟一个或多个小写字母,再跟一个
空格。
匹配操作符(~)、否定号(!)用来与以条记录或域里的表达式相匹配。
例子:
$ awk '$1 ~/[Bb]ill/' employees
Billy Black 1683 9/23/44 336500
解释:awk将显示第一个域里与Bill或者bill相匹配的行
$ awk '$1 !~/ly$/' employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
解释:显示第一个域中末尾不是ly的所有行。
8.写在命令表文件中的awk命令
写awk命令表的方法可以参考chap05/info文件。该文件内容如下:
# Here is a sample script:
#****************************************************************
*
# My first awk script by Jack Sprat
# Script name: info; Date: February 28, 1999
/Tom/{print "Tom's birthday is " $3}
/Mary/{print NR, $0}
/^Sally/{print "Hi Sally, " $1 " has a salary of $" $4 "."}
#End of script
9.练习题参考答案
习题文件是chap05/donors,部分内容如下:
Mike Harrington 510) 548-1278:250:100:175
Christian Dobbins 40 538-2358:155:90:201
Susan Dalsass 206) 654-6279:250:60:50
Archie McNichol 206) 548-1348:250:100:175
上面的数据库包含名字、电话号码和过去三个月的竞选捐款。
1〉打印所有的电话号码
$ awk -F: '{print $2}' donors
2〉打印Dan的电话号码
$ awk -F: '/^Dan/{print $2}' donors
3〉打印Susan的名字和电话号码
$ nawk -F'[ :/t]' '/^Susan/{print $1,$3,$4}' donors
4〉打印所有以D开头的姓
$ awk '$2 ~/^D/{print $2}' donors
5〉打印所有以一个C或E开头的名
$ awk '/^[CE]/{print $1}' donors
6〉打印所有只有四个字符的名
$ nawk '/^[A-Z][a-z][a-z][a-z] /{print $1}' donors
7〉打印所有那些区号是916的名
$ awk -F: '$2 ~/916/{print $1}' donors
8〉打印Mike的活动捐款。打印每个值时都要以一个美元符号打头;例如:
$500$200$300
$ awk -F: '/^Mike/{printf "$%d$%d$%d/n",$3,$4,$5}' donors
9〉打印姓,其后跟一个逗号和名
$ nawk -F'[ :/t]' '{printf "%s,%s/n",$2,$1}' donors
10〉 写一个叫facts的awk命令表,它能:
a. 打印Savages的全名和电话号码
b. 打印Chet的捐款
c. 打印所有第一个月捐款$250的人
文件内容如下:
$ cat facts
#My first awk scripts by wangzhh.
/Savage/{print $1,$2}
/^Chet/{printf "Beneficence of Chet: $%d$%d$%d/n",$3,$4,$5}
$3 ~/250/{printf " erson who's beneficence is 250:%s/n",$1}
调用方法:
nawk -F: -f facts donors
第6章 awk实用程序:awk编程结构
比较表达式比较行,如果行里的条件为真,就执行操作。如果给表达式求值
为真则值等于1,反之等于0。
1.关系操作符
下表列出了关系操作符。
操作符
含义
例子
<
小于
x<y
<=
小于等于
x<=y
==
等于
x==y
!=
不等于
x!=y
>;=
大于等于
x>;=y
>;
大于
x>;y
~
与正则表达式相匹配
x~/y/
!~
不与正则表达式相匹配
x!~/y/
表6.1关系操作符
关系操作符举例:
$ cat employees
Tom Jones 4423 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
$ awk '$3==4423' employees
Tom Jones 4423 5/12/66 543354
$ nawk '$3 >;5000{print $1}' employees
Mary
$ nawk '$2 !~/Adam/' employees
Tom Jones 4423 5/12/66 543354
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
条件表达式:一个条件表达式用两个符号,问号和冒号来给表达式求值。与
一个if/else语句相比更简介。
2.条件表达式
格式:
conditional expression1?expression2:expression3
它等同于{if(expression1)
expression2
else
expression3
}
条件表达式举例:
nawk '{max=($1>;$2)?$1 2;print max}' employees
解释:如果第一个域大于第二个域,就把第一个域的内容赋给max,反之把第
二个域的内容赋给max,然后打印max
3.计算
可以在模式里执行计算。awk以浮点方式执行所有的算术运算。
操作符
含义
例子
+
加
x+y
-
减
x-y
*
乘
x*y
/
除
x/y
%
求模
x%y
^
幂运算
x^y
表6.2 算术运算操作符
4.复合模式
复合模式 (compound patterns) 是把模式和逻辑操作符相结合的表达式,给
一个表达式从左到右求值。
操作符
含义
例子
&&
逻辑与
a&&b
||
逻辑或
a||b
!
逻辑非
!a
表6.3 逻辑操作符
复合模式举例:
$ nawk '$3>;4000 && $3<=6000' employees
Tom Jones 4423 5/12/66 543354
Mary Adams 5346 11/4/63 28765
$ nawk '!($3>;4000 && $3<=6000)' employees
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
5.范围模式
范围模式从一个模式的第一次出现匹配到第二个模式的第一次出现,然后从
第一个模式的第二次出现匹配到第二个模式的第二次出现等等。如果第一个
模式被匹配,而第二个模式没有找到,则awk将显示直到末尾的所有行。
例子:
$ cat datafile
northwest NW Joel Craig 3.0 .98 3 4
western WE Sharon Kelly 5.3 .97 5 23
southwest SW Chris Foster 2.7 .8 2 18
southern SO May Chin 5.1 .95 4 15
southeast SE Derek Johnson 4.0 .7 4 17
eastern EA Susan Beal 4.4 .84 5 20
northeast NE TJ Nichols 5.1 .94 3 13
north NO Val Shultz 4.5 .89 5 9
central CT Sheri Watson 5.7 .94 5 13
$ nawk '/^north/,/^west/' datafile
northwest NW Joel Craig 3.0 .98 3 4
western WE Sharon Kelly 5.3 .97 5 23
northeast NE TJ Nichols 5.1 .94 3 13
north NO Val Shultz 4.5 .89 5 9
central CT Sheri Watson 5.7 .94 5 13
6.一个数据有效性检查程序
本例子使用chap06/passwd文件,内容如下:
tooth:pwHfudo.eC9sM:476:40:Contract Admin.:/home/rickenbacker/tooth:/bin/csh
lisam:9JY7OuS2f3lHY:4467:40:Lisa M. Spencer:/home/fortune1/lisam:/bin/csh
goode:v7Ww.nWJCeSIQ:32555:60:Goodwill Guest User:/usr/goodwill:/bin/csh
bonzo:eTZbu6M2jM7VA:5101:911: SSTOOL Log account :/home/sun4/bonzo:/bin/csh
info:mKZsrioPtW9hA:611:41:Terri Stern:/home/chewie/info:/bin/csh
cnc:IN1IVqVj1bVv2:10209:41:Charles Carnell:/home/christine/cnc:/bin/csh
bee:*:347:40:Contract Temp.:/home/chanel5/bee:/bin/csh
friedman yuIiKoFTV0TE:3561:50:Jay Friedman:/home/ibanez/friedman:/bin/csh
chambers:Rw7R1k77yUY4.:592:40:Carol Chambers:/usr/callisto2/chambers:/bin/csh
gregc:nkLulOg:7777:30:Greg Champlin FE Chicago
ramona:gbDQLdDBeRc46:16660:68:RamonaLeininge MWA CustomerService Rep:/home/forsh:/bin/csh
要求程序能够显示域个数不等于7的行、第一个域不包含数字字母的行、第
二个域等于星号的行。程序写在ex_6.8.nawk文件中,内容如下:
# nawk script (covered later in the chapter)
# To demonstrate example 6.8 using this script, run
# % nawk -f ex_6.8.nawk passwd
BEGIN {FS = ":"}
NF != 7 { printf("line %d, does not have 7 fields: %s/n",NR,$0)}
$1 !~ /[A-Za-z0-9]/{printf("line %d, nonalphanumeric user id: %s/n"NR,$0)}
$2 == "*" {printf("line %d, no password: %s/n",NR,$0)}
下面是调用方法和执行结果:
$ awk -f ex_6.8.nawk passwd
line 7, no password: bee:*:347:40:Contract Temp.:/home/chanel5/bee:/bin/csh
line 10, does not have 7 fields: gregc:nkLulOg:7777:30:Greg Champlin FE Chicago
7.练习题参考答案
联系文件是chap06下的lab4.data,内容如下:
Mike Harrington 510) 548-1278:250:100:175
Christian Dobbins 40 538-2358:155:90:201
Susan Dalsass 206) 654-6279:250:60:50
Archie McNichol 206) 548-1348:250:100:175
Jody Savage 206) 548-1278:15:188:150
Guy Quigley 916) 343-6410:250:100:175
Dan Savage:(406) 298-7744:450:300:275
Nancy McNeil:(206) 548-1278:250:80:75
John Goldenrod:(916) 348-4278:250:100:175
Chet Main:(510) 548-5258:50:95:135
Tom Savage:(40 926-3456:250:168:200
Elizabeth Stachelin:(916) 440-1763:175:75:300
1>; 打印那些第一个月捐款超过100的人的姓名
$ awk -F: '$3>;100 {print $1}' lab4.data
2>; 打印那些第一个月捐款少于$60的人的姓名和电话号码
$ awk -F: '$3<60{print $1,$2}' lab4.data
3>; 打印那些第三个月捐款在90到150之间的人
$ awk -F: '$5>;=90 && $5<=150 {print $0}' lab4.data
4>; 打印那些三个月捐款在800以上的人
$ awk -F: '$3+$4+$5>;800 {print $0}' lab4.data
5>; 打印那些平均每月捐款大于$150的人名和点话号码
$ nawk -F'[ :/t]' '($5+$6+$7)/3>;150{print $1,$3,$4}' lab4.data
6>; 打印那些区号不是916的人名
$ nawk -F'[ :/t]' '$3 !~/916/{print $1}' lab4.data
7>; 打印每条记录,记录号在前面
$ awk '{print NR,$0}' lab4.data
8>; 打印每个人的名字和捐款总额
$ nawk -F'[ :/t]' 'sum=($5+$6+$7) {print $1,sum}' lab4.data
9>; 把Elizabeth的第二次捐款加上$10
$ nawk -F'[ :/t]' 'juankuan=($1 ~/Elizabeth/)?$6+10 6{print $1,juankuan}' lab4.data
10>;把Nancy McNeil的名字改成Louise McInnes
$ nawk 'name=($1 ~/Nancy/)?"Louise McInnes" 1{print name}' lab4.data
第7章 awk实用程序:awk编程
1.变量
.. 数值和串常数
数值常数可以表示成整数、浮点、科学计数等。含有空格的串要封装在
双引号里。例如"Hello world"。如果一个域或这数组元素为空,则串值
为空。一个空行也被当作空串。
.. 用户自定义变量
用户自定义变量包括字母、数字和下划线,且不能以数字开头。在awk
中变量不用声明,awk通过表达式的上下文推断变量类型,并且如果需
要,还可以在不同类型的变量中相互转换。
.. 递加和递减操作符(++和--)
与c++语言中一样。x++是后递加,++x是先递加。
.. 内置变量。
内值变量要大写,他们可以用在表达式里而且可以被重置。如下表
变量名
含义
ARGC
命令行变元个数
ARGV
命令行变元组数
FILENAME
当前输入文件名
FNR
当前文件里的记录号
FS
输入域分隔符,默认是空格
NF
当前域里的域个数
NR
到目前为止的记录数
OFMT
数值输出格式
OFS
输出域分隔符
ORS
输出记录分隔符
RLENGTH
由match函数匹配的串的长度
RS
输入记录分隔符
RSTART
由match函数匹配的串偏移量
SUBSEP
下标分隔符
表7.2 nawk内置变量
内置变量举例:
$ nawk -F: '$1=="Mary Adams"{print NR,$1,$2,$NF}' employees2
2 Mary Adams 5346 28765
解释:-F选项把分隔符改成冒号。如果域1等于Mary Adams,则打印记
录号、第一个域、第二个域和最后一个域($NF)
.. BEGIN模式
BEGIN模式后面跟一个操作模块,在awk处理文件之前执行该模块。BEGIN
模式主要用来设置OFS、RS、FS等内置变量的值。
$ awk 'BEGIN{FS=":";OFS="/t";ORS="/n/n"}{print $1,$2,$3}' employees2
Tom Jones 4423 5/12/66
Mary Adams 5346 11/4/63
Sally Chang 1654 7/22/54
Mary Black 1683 9/23/44
解释:在处理输入文件之前,把域分隔符置成一个冒号,输出域分隔符
制成跳格符,并把输出记录分隔符(ORS)设置成两个换行符。
.. END模式
END模式不与任何输入行相匹配,但是执行任何与END模式相关的操作。
在所有行处理完毕之后再来处理END模式。
$ awk '/Mary/{count++}END{print "Mary was found " count " times."}' employees
Mary was found 1 times.
解释:对于包含Mary的每一行,count变量值都递增1。awk 处理完毕之
后,END模块打印结果。
2.重定向和管道
.. 输出重定向:当把输出从awk重定向到一个UNIX文件时,使用shell
重定向操作符。如果重定向操作符用在awk命令里面则必须将重定向文
件用双引号括起来。例如:
$ awk '$4>;70 {print $1,$2 >;"passing_film"}' datafile
.. 输入重定向(getline)
getline 函数用来从标准输入,例如管道或者文件来读入数据,而不是
从正被处理的当前文件。getline 取得输入的下一行,并更新NF、NR
和FNR等内置变量的值。如果getline找到记录则返回1,达到EOF(文
件结束)则返回0。如果有错误则返回-1。
.. 举例1:
$ nawk 'BEGIN{"date"|getline d;print d}' datafile
2005年05月06日 星期五 15时05分41秒 CST
解释:执行date命令,然后把输出从管道送到getline,并赋给自
定义变量d,然后打印d。
.. 举例2:
$ nawk 'BEGIN{while("ls"|getline) print}'
awk.sc2
datafile
datafile2
employees
employees2
lab5.data
names
passwd
解释:将把ls的输出送到getline。对于每次循环,getline都从
ls读取一个以上输出,然后打印到屏幕上
.. 举例3:
$ nawk 'BEGIN{printf "What is your name?";/
>; getline name<"/dev/tty"}/
>; $1 ~ name {print "Found " name " on line ",NR "."}/
>; END{print "See ya, " name "."}' employees
What is your name?Wangzhonghai
See ya, Wangzhonghai.
解释:将在屏幕上打印What is your name?,并且等待用户响应。
getline 函数将从终端(/dev/tty)接受输入,一直到输入一个换行
符为止,然后把输入存到用户自定义变量name中。如果递一个域和
name的值相匹配,则执行print函数。在END模式中打印”See ya,”
然后跟name的值。
.. 举例4
$ nawk 'BEGIN{while (getline<"/etc/passwd">;0)lc++;print lc}'
16
解释:awk将从“/etc/passwd”读取各行,lc递增,直到EOF,然
后打印lc的值。
3.管道
如果在一个awk程序中打开一个管道,则必须在打开另一个之前先关闭它。
在管道符号由变的命令封装在双引号里。一次只能打开一个管道。下面的例
子是将names文件中的姓名按照姓作为第一关键字,名作为第二关键字来进
行倒排序:
$ awk '{print $1,$2|"sort -r +1 -2 +0 -1 "}' names
tony tram
john smith
dan savage
barbara nguyen
elizabeth lone
john goldenrod
susan goldberg
george goldberg
eliza goldberg
alice cheba
4.关闭文件和管道
如果在awk中再次使用一个文件或者管道来读取或写入,则需要首先关闭管
道。打开和关闭管道的例子可以参考/chap07/awk.sc3文件。(书中源代码没
有这个文件,而书上错误很多。)
5.回顾(略)
6.条件语句
1) if 语句
以if结构开头的语句是操作语句。在条件模式(conditional patterns)
里,if是隐含的;在一个条件操作语句中,if要显式说明,并且后面跟
一个封装在括弧里的表达式。如果跟在条件表达式后面的语句不止一条,
则语句组必须放在花括号里,并且用分号或者换行符来分开。
格式:
if (expression){statement;statement;…}
举例1:
$ nawk '{if($8>;15) print $1 " To high"}' datafile
举例2:
$ nawk '{if($8>;15 && $8<=23){safe++; print $1 " OK " safe}}' datafile
2) if/else语句
if/else语句允许一个二路判断。
格式:
{if(expression) {
statement;statement;…
}
else{
statement;statement;…
}
}
3) if/else else if语句
允许多路判断。
格式:
{if (expression) {
statement;statement;…
}
else if (expression){
statement;statement;…
}
else if (expression){
statement;statement;…
}
else{
statement;statement;…
}
}
7.循环
循环的作用是,如果一个条件为真,则重复执行测试表达式后的语句。循环
通常用来迭代一条记录里的域,及循环操作END模块里的一个数组的元素。
awk 有3种循环:while循环、for循环和特殊for循环。
1) while循环
使用规则与c中一样。
举例:
$ nawk '{i=1;while(i<=NF){print NF,$i;i++}}' datafile
解释:变量i初始化为1;当I小于或等于记录中的域个数(NF)时,执行
print并让i递增,然后再测试表达式,直到i>;NF。读取下一条的记录的
时候i被重新初始化。
2) for循环
使用规则与c中一样。
举例:
$ nawk '{ for (i=1;i<=NF;i++) print NF,$i}' datafile
3) 循环控制:break和continue
break 和 continue。break 让你在某个条件为真时调出循环。continue
使循环在某个条件为真时条过后面的任何语句,并把控制返回循环顶部,
开始下一次迭代。
举例:
{for (x=3;x<=NF;x++)
if($x<0){print "Bottomed out!";break}
#breaks out of for loop
}
举例2:
{for (x=3;x<=NF;x++)
if($x==0){print "Get next item!";continue}
#starts next item of for loop
}
8.程序控制语句
1) next 语句
next 语句从输入文件取得下一个输入行,在awk命令表顶部重新开始执
行。
举例:
$ awk '{if($1 ~/Tom/){next} else {print}}' db
解释:如果第一个域包含Tom,则略过。
2) exit语句
exit 语句用来终止awk程序。它停止处理记录,但是不跳过END语句。
3)
9.数组
在awk中数组叫做关联数组(associative arrays),因为下标记可以是数也
可以是串。awk中的数组不必提前声明,也不必声明大小。数组元素用0或
空串来初始化,这根据上下文而定。
1) 关联数组的下标
.. 把变量用作数组索引。
举例:
$ nawk '{name[x++]=$2};END{for(i=0;i<NR;i++)/
>; print i,name }' employees
0 Jones
1 Adams
2 Chang
3 Black
解释:在数组name里的下标是一个用户自定义变量x。++显示了一个
数值型的上下文。
.. 特殊for循环
在for循环无效的情况下,即当串被用作下标或者下标不是连续的数
时,用特殊for循环来读取一个关联数组。特殊for循环把下标当作
一个键来找到它的相关的值。
格式:
{for(item in arrayname){
print arrayname[item]}}
举例:
$ nawk '/^Tom/{name[NR]=$1};/
>; END{for(i=1;i<=NR;i++) print name}' db
Tom
Tom
Tom
Tommy
$ nawk '/^Tom/{name[NR]=$1};/
>; END{for(i in name){print name}}' db
Tom
Tom
Tommy
Tom
解释:这两个例子用NR(行号)来做下标,因此匹配Tom的模式的行
不连续,数组下标不连续。如果用传统for来循环打印会在数组没有
值的地方打印空值。通过使用特殊for循环,只打印数组中有值的内
容。
..
2)
10.
附录B 比较三种shell
特性
C shell
Bounne shell
Korn shell
变量
给局域变量赋
值
set x=5
s=5
s=5
赋变量属性
typeset
给环境变量赋
值
setenv NAME Bob
NAME=Bob
export NAME=Bob
存取变量
echo $NAME
set var=net
echo ${var}work
network
echo $NAME
var=net
echo ${var}work
network
echo $NAME或print
$NAME
var=net
print ${var}work
network
专用
变量
该进程的PID
$$
$$
$$
退出状态
$status
$?
$?
上一个后台作
业
$!
$!
数组
给数组赋值
Set x=(a b c)
N/A
Y[0]=a;y[1]=b;y[2]=c
Set –A fruit apples
pears plums
1. 定义
shell 是一种特殊的程序,被用作用户与内核(kernel)的UNIX操作系统核心
通讯。常见的shell有C shell、B shell 和 Korn shell(B shell的超集)。
2. shell 主要功能
.. 解释交互运行时,在命令行提示下敲入的命令
.. 制订用户环境,通常在shell初始化文件中作这种工作。例如:设置终
端键及窗口特征;设置搜索路径、权限、提示等
.. shell 可以用作解释编程语言。Shell程序也叫命令表,由再文件中列出
的命令组成。
3. 主要shell命令:
who mv rm wc ls cat date at
lpr rsh more awk pwd bc vi finger w
pg find cc cp dd grep ksh sh
ps sed cal lp
第2章 UNIX工具箱
1.正则表达式
一个正则表达式就是用来在一次搜索中匹配相同字符的一个字符模式。在大
多数程序中,把一个正则表达式封装在正斜杠(/)里。
2.正则表达式元字符
元字符
功能
实例
解释
^
行开头定位
/^love/
与所有love开头的行匹配
$
行末尾定位
/love$/
与所有love结尾的行匹配
.
匹配单个字符
/l..e/
与包含一个l,后跟两个字符,然后跟一个e的行相匹配 *
跟前驱的0个或多
个字符相匹配
/ *love/
跟0个或多个空格后面的
love模式的行相匹配
[]
与其中的一个相匹
配
/[Ll]ove/
与包含love或者Love的行
匹配
[x-z]
与集中一个范围内
的一个字符相匹配
/[A-Z]ove/
与后面跟ove的从A到Z的
字相匹配
[^]
与不在集里的字符
匹配
/[^A-Z]ove/
不包括A到Z,后面跟ove
的字相匹配
/
给一个元字符转移
/love/./
匹配行包括love,跟一个句
点
许多用RE元字符的UNIX程序支持的附加元字符(vi 和 grep支持)
/<
词开头定位
//<love/
匹配行包含用love开头的
词
/>;
词结尾定位
/love/>;/
匹配行包含love结尾的词
/(../)
标志与以后用的字
符相匹配
/(love/)able/ler/
Able可达9个标志,模式最
左边用第一个标志开始。例
如,模式love保存作标志
l,以后引用作/l;在这个例
子中,搜索模式包括后面跟
lover的lovable
x/{m/}
x/{m,/}
x/{m,n/}
字符x重复m次
至少m次
m到n次
O/{5,10/}
如果行包含5—10个连续的
o则匹配
表(2.1)
3.举例
查找文件中的含有love的词:
% vi picnic
I had a lovely time on our little picnic. Lovers were all around
us, oh love
:/love/
4.组合正则表达式元字符
文件内容:(数字是行号,竖线标明行的左右边界,不属于文件内容。这个文
件我写在shell/exam/exam_2.9中)
1 |Christian Scott lives here and will put on a Christmas party.|
2 |There are around 30 to 35 people invited.|
3 |They are: |
4 | Tom|
5 |Dan|
6 | Rhonda Savage|
7 |Nicky and Kimerly.|
8 |Steve, Suzanne, Ginger and Larry.|
组合举例:
.. /^[A-Z]..$/
搜索行以A至Z的一个字母开头,然后跟两个任意字母,然后跟一
个换行符的行。将找到第5行。
.. /^[A-Z][a-z]*3[0-5]/
搜索以一个大写字母开头,后跟0个或多个小写字母,再跟数字3,
再跟0—5之间的一个数字。
.. *[A-Z][a-z][a-z]$/
搜索以0个或多个空格开头,跟一个大写字母,两个小写字母和一
个换车符。将找到第4行的TOM(整行匹配)和第5行。注意,*前
面有一个空格。
.. /^[A-Za-z]*[^,][A-Za-z]*$/
将查找以0个或多个大写或小写字母开头,不跟逗号,然后跟0个
或多个大写或小写字母,然后跟一个换车符。将找到第5行。书中
解释有误。
5.更多的正则表达式元字符
这里讨论的元字符不一定可以移植到所有的正则表达式中,但一般可以用在
vi、sed和grep中。
% vi textfile
Patty won fourth place in the 50 yard dash square and fair.
Occurences like this are rare.
Haha, what you want is just fourth.
~
~
://<fourth/>;/
将查找词fourth
第3章 grep家族
1.grep的含义是“全局搜索正则表达式(RE)并打印该行”
2.grep支持的正则表达式
与在文件中搜索基本一样。可以参考表2.1。
3.grep 的选项
选项
功能
-b
在各行之前放置它发现的块号。有时在根据上下文定位磁盘字块时有用
-c
显示匹配行数而不是内容
-h
不显示文件名
-I
在座比较时忽略字母大小写
-n
文件中每行之前给出它的相关行号
-s
无声操作。即除了错误消息外不做任何显示。用于检查退出状态
-v
把搜索翻转为只显示不匹配的行
-w
把表达式当作一个次来搜索,相当于用/<和/>;括起来
表3.1
4.grep命令的退出状态
如果grep操作成功,则状态是0,如果模式没找到,状态是1,如果文件没
找到,状态是2。如果操作被取消,则状态是130。查看状态的方法:在csh
中用echo $status。在sh和ksh中用echo $? 。例如
$ echo $?
0
5.带正则表达式的grep举例:
用于这些例子的文件叫datafile,位于chap03目录。内容如下:
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
1) grep NW datafile
解释:打印datafile中包含NW的行
2) grep NW d*
解释:打印所有以d开头的文件中含有NW的文件。
3) grep '^n' datafile
解释:打印文件datafile中所有以字母n开头的行
4) grep TB Savage datafile
解释:在Savage和datafile文件中查找有TB的行
5) grep 'TB Savage' datafile
解释:在datafile文件中查找含有TB Savage的行并打印。这个例子在
书中有误。
6) grep '^[we]' datafile
打印datafile中以w或者e开头的行
7) grep 'ss* ' datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
解释:打印所有包含一个s并跟0个或者多个s,然后跟一个空格的行
6.用管道的grep
grep 可以从管道得到输入。
% ls –l
drwxr-xr-x 6 oracle dba 512 4月 3 21:49 chap10
drwxr-xr-x 2 oracle dba 512 4月 10 22:23 exam
-rwxr--r-- 1 oracle dba 1842 4月 3 21:51 readme.txt
-rwxr--r-- 1 oracle dba 1801 4月 3 21:51 unix_readme.txt
% ls –l | grep '^d'
drwxr-xr-x 6 oracle dba 512 4月 3 21:49 chap10
drwxr-xr-x 2 oracle dba 512 4月 10 22:23 exam
% ls -l |grep '^[^d]'
-rwxr--r-- 1 oracle dba 1842 4月 3 21:51 readme.txt
-rwxr--r-- 1 oracle dba 1801 4月 3 21:51 unix_readme.txt
7.带选项的grep举例:
grep –c ‘west’ datafile
3
解释计算datafile中含有west的总数。
8.egrep (扩展的grep)
egrep可以使用额外的正则表达式,如下表。
元字符
功能
例子
解释
+
匹配一个或多个前驱字符
'[a-z]+ove'
匹配一个或多个小写
字母,后跟ove
?
匹配0个或者1个前驱字
符
'lo?ve'
将找到love或love
a|b
匹配a或者b
'love|hate'
与love或hate匹配
()
组字符
'lov(ely|able)
与lovely或lovable
匹配
表3.2
9.egrep 举例:
egrep '2/.?[0-9]' datafile
解释:打印所有这样的行:它包含一个2,后跟0个或者一个句号,然后跟
一个数字。
10. fgrep
fgrep 把所有的元字符都当作字符本身,只代表自己。
11. UNIX 工具试验参考答案(内容参考datebook)
.. 打印包含San的行
grep 'San' datebook
.. 打印所有以J开头的人名所在的行
grep '^J' datebook
.. 打印以700结尾的行
grep '700$' datebook
.. 打印所有不包含834的行
grep -v '834' datebook
.. 打印出生在12月(December)的行
grep '/12' datebook
.. 打印工资是6位数的行,并给出行号
grep -n '[0-9]/{6,/}$' datebook
第4章 流编辑器(sed)
1. sed 命令简介
sed 是流线型、非交互式编辑器。它允许你执行与vi 和ex编辑器里一样的
编辑任务。Sed 程序不是与编辑器交互式工作的,而是让你在命令行里敲入编辑
的命令,给文件命名,然后在屏幕上查看命令输出结果。
2. sed 如何工作
sed 编辑器按一次处理一行的方式来处理文件,并把输出送到屏幕上。
3. sed 可以用寻址的方式来决定想要编辑哪一行。
4. sed 命令和选项
命令
功能
a/
在当前行上添加一个文本行或者多个文本行
c/
用新闻本改变(取代)当前行里的文本
d
删除行
i/
在当前行之前插入文本
h
把模式空间内容复制到一个固定缓存
H
把模式空间内容添加到一个固定缓存
g
得到固定缓存里所有的禀复制到模式缓存,重写其内容
G
得到固定缓存的内容并复制到模式缓存,添加到里面
I
列出不打印的字符
p
打印行
n
读下一输入行,并开始用下一个命令处理换行符,而不是用第一个
命令
q
结束或退出sed
r
从一个文件读如行
!
把命令应用到除了选出的行以外的其他所有行
s
把一个字串替换成另一个
替换标志
g
在一行上进行全局替换
p
打印行
w
把行写到一个文件中
x
用模式空间的内容交换固定缓存的内容
y
把一个字符转换成另一个(不能和整则表达式元字符一起使用)
5. sed 元字符
基本上,grep和vi使用的元字符都可以用在sed中。具体可参照第二章。
下表列出了一些特别的sed 元字符:
元字符
功能
例子
解释
&
保存搜索串以便可
以记在替换串里
s/love/**&**/
&号代表搜索串。串love将被星
号包围的自身所替代;即love
变成**love**
6. sed 的实例(使用datafile)
1>; 打印:p命令
sed '/north/p' datafile
默认输出所有行,找到north的行重复打印
sed –n '/north/p' datafile
禁止默认输出,只打印找到north的行
2>; 删除:d命令
sed '3d' datafile
删除第三行,其余行输出到屏幕
sed '3,$d' datafile
从第3行到最后一行都删除,将剩余部分输出到屏幕
sed '/north/d' datafile
将含有north的行删除,其余输出到屏幕
3>; 替换:s命令
sed 's/west/north/g' datafile
解释:找到datafile中的所有west并替换成north,将替换后的内容输
出到屏幕。
sed 's/[0-9][0-9]$/&.5/' datafile
解释:在替代串里的&字符代表在搜索串中真正找到的。每个以两个数字
结尾的行都被它自己取代,且要在后面加上.5
sed -n 's/Hemenway/Jones/gp' datafile
解释:所有的Hemenway所在的位置都用Jones来取代,而且只有改变的
行被打印。-n与p命令选项相结合来禁止默认输出。g代表全局替换
sed -n 's//(Mar/)got//1ianne/p' datafile
解释:模式Mar被封装在括弧里且在一个专用寄存器里存为标记1。在替
换串里它将被引用做/1。然后用Marianne替代Margot。
sed 's#3#88#g' datafile
s命令后面的字符是搜索串和替换串之间的分界符。默认的分界符是一个
正斜杠,但也可以改变(只有使用s命令时)。无论s命令后面跟什么字
符,它都是新的串分界符。当搜索包含一个正斜杠的模式,如路径或生
日时,这种技巧可能有用
4>; 被选中的行的范围:逗号
sed -n '/west/,/east/p' datafile
打印在west和east之间的模式范围内所有行。如果west出现在east
之后,则打印从west到下一个east或者到文件末尾的行,无论哪种情
况先出现都可以。
sed '/west/,/east/s/$/**VACA**/' datafile
解释:对于在模式west到east范围内的行,行末尾将用**VACA**来取代。
5>; 多次编辑 -e 选项
sed -e '1,3d' -e 's/Hemenway/Jones/' datafile
-e选项允许多次编辑。不同的编辑顺序可能导致不同的结果。例如,如
果两个命令都执行了替换,第一次替换可能影响第二次替换。
6>; 从文件中读取:r命令
sed '/Suan/r newfile' datafile
解释:r命令从newfile中读取内容,将内容输出到Suan的后面。如果
datafile中Suan出现的次数不只一次,则分别放到Suan的后面。
7>; 写入文件:w命令
sed -n '/north/w newfile' datafile
解释:w命令把指定的行写入到一个文件。本例中所有的包含north的行
写入到newfile中。等同于sed -n '/north/p' datafile >;newfile
8>; 添加:a命令
$ sed '/north/a/
>; ---->;THE NORTH SALES DISTRICT HAS MOVED<-----' datafile
northwest NW Charles Main 3.0 .98 3 34
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
north NO Margot Weber 4.5 .89 5 9
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
central CT Ann Stephens 5.7 .94 5 13
解释:红颜色的内容是要输入的内容。a/命令后面跟要添加的内容。奇怪的是a/后
面必须另起一行,在输入要添加的内容,否则会提示命令错乱,真是搞不懂。
9>; 插入:i命令
$ sed '/north/i/
>; ---->;THE NORTH SALES DISTRICT HAS MOVED<-----' datafile
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
northeast NE AM Main Jr. 5.1 .94 3 13
---->;THE NORTH SALES DISTRICT HAS MOVED<-----
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
解释:在符合模式的行前面插入内容。其余和a/命令相同。
10>;下一个:n命令
$ sed '/eastern/{n;s/AM/Archie/;}' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE Archie Main Jr. 5.1 .94 3 13
……
解释:如果在某一行里模式eastern被匹配,n命令使sed区的下一行,
用该行带换模式空间,用Archie替换AM,打印并继续。
11>;变换:y 命令
sed '1,3y/abcdefghijklmnopqrst/ABCDEFGHIJKLMNOPQRST/' datafile
解释将对应字母进行转换。
12>;退出:q 命令
sed '5q' datafile
解释:在打印了5行之后,用q命令退出sed程序。
13>;保存和取得:h和G命令
$ sed -e '/southeast/h' -e '$G' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
southeast SE Patricia Hemenway 4.0 .7 4 17
解释:当sed 处理文件时,每行都存在模式空间(pattern space)的临时缓存中。
除非行被禁止打印或删除,否则行将在处理完后被打印到屏幕,然后请模式空间并把
下一输入行保存在那里等待处理。在这个例子中,在找到模式之后,把它放在模式
空间里,而且h命令复制它并把它存到另一个叫做保存缓存(holding buffer)中。
第二个sed指令里,当读入最后一行($)时,G命令告诉sed从包存缓存中取得该行
并放回模式空间缓存,添加到当前存在那里的行中。本例子就是最后一行。
$ sed -e '/WE/{h;d;}' -e '/CT/G' datafile
northwest NW Charles Main 3.0 .98 3 34
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
north NO Margot Weber 4.5 .89 5 9
central CT Ann Stephens 5.7 .94 5 13
western WE Sharon Gray 5.3 .97 5 23
解释:第一个命令h将找到了WE的行放到保存缓存中,然后删除该行;第二个命令
/CT/G就是在找到了CT的行的后面加入保存缓存的内容。
14>;G和g的区别
G命令在符合的条件行后面添加保存缓存中的内容;g命令用保存缓存中
的内容覆盖符合条件的行。
15>;sed 命令的花括号{}的作用
花括号{}中可以放入多个命令,每个命令后面要用分号;。
16>;保存和交换:h 和 x命令。
$ sed -e '/Patricia/h' -e '/Margot/x' datafile
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
southeast SE Patricia Hemenway 4.0 .7 4 17
central CT Ann Stephens 5.7 .94 5 13
解释:x命令将找到的行用保存缓存中的内容替换。
7. 用sed来编写命令表
sed 命令表(script)是文件里的一个sed命令列表。用-f选项来引用一
个命令表文件。编辑sed命令表有特殊要求:命令末尾不能有任何为岁的空
白符或者文本。如果命令不是自成一行,就必须用分号结束。在源代码chap4
目录下有两个编辑好的命令表文件(sedding1和sedding2)可以参考。下面是
使用sed命令表的例子。
$ sed -f sedding1 datafile
EMPLOYEE DATABASE
---------------------
northwest NW Charles Main 3.0 .98 3 34
western WE Sharon Gray 5.3 .97 5 23
southwest SW Lewis Dalsass 2.7 .8 2 18
Lewis is the TOP Salesperson for April!!
Lewis is moving to the southern district next month.
CONGRATULATIONS!
southern SO Suan Chin 5.1 .95 4 15
southeast SE Patricia Hemenway 4.0 .7 4 17
eastern EA TB Savage 4.4 .84 5 20
northeast NE AM Main Jr. 5.1 .94 3 13
*******************
MARGOT HAS RETIRED
*******************
8. Sed练习参考答案
练习内容参考databook文件
1〉 把Jon改成Jonathan
sed 's/Jon/Jonathan/' datebook
2〉 删除头3行
sed '1,3d' datebook
3〉 打印5—10行
sed -n '5,10p' datebook
4〉 删除包含Lane的行
sed '/Lane/d' datebook
5〉 打印所有生日是在Noverber到December之间的行
sed -n '/:1[12]///p' datebook
6〉 把三个星添加到以Fred开头的行尾
sed '/^Fred/s/$/***/' datebook
7〉 用JOSE HAS RETIRED取代包含Jose的行
sed 's/^Jose[0-9]*[a-z]*[A-Z]* *.*$/JOSE HAS LEFT/' datebook
8〉 把Popeye的生日改成11/14/46
sed '/Popeye/s/:[0-9]*[0-9]*//[0-9]*[0-9]*//[0-9]*[0-9]*/:11//14//46/' datebook
9〉 删除所有空白行
sed '/^$/d' datebook
10〉 写一个sed命令表,将:
a. 在第1行之前插入标题PERSONNEL FILE
b. 删除以500结尾的工资
c. 打印文件内容,把姓和名颠倒
d. 在文件末尾添加THE END
答案放在chap04/a10文件中,内容如下:
# My first sed script by Wangzhh.
1i/
PERSONNEL FILE
/500/d
s//([A-Z][a-z]*/) /([A-Z][a-z]*/)://2 /1:/
$a/
THE END
第5章 awk 实用程序:awk作为一种UNIX工具
1. awk 简介
awk 是用来操作数据和产生报表的一种编程语言。数据可能来自标准输入、
一个或者多个文件或者是一个进程的输出。awk 可以用在命令行里用于简单
操作,或者可以为了较大的应用而写到程序中。常见的awk命令有awk、nawk
等。awk从第1行到最后一行逐行扫描文件(或输入),并执行选定的操作(封
装在花括号里)。本文章所有的例子使用的文件未经说明都在chap05目录下。
2. awk的格式
awk程序由awk命令,封装在引号里(或在一个文件里)的程序指令,和输
入文件组成。如果没有指定一个输入文件,则输入来自标准输入(stin)键盘。
employees文件中的内容:
$ cat employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
1〉从文件输入
$ awk '/Mary/' employees
解释:打印employees文件中含有Mary的行
$ awk '{print $1}' employees
Tom
Mary
Sally
Billy
解释:打印文件employees中的第一个域。域的分隔符是空格。
nawk '/Sally/{print $1,$2}' employees
解释:只有找到了Sally的行才打印第一个域和第二个域。
2〉管道输入
$ df -k|awk '$4>;1024000'
解释:报告剩余空间大于1024000k的盘。
3. 格式化输出
1〉print函数
例子1:
$ date
2005年04月30日 星期六 19时29分25秒 CST
$ date|awk '{print "Date:" $1 "/nTime:" $3}'
Date:2005年04月30日
Time:19时34分24秒
注意,用date命令查看时间格式。不同的语言可能格式也不一样,因此
awk也要随之而变。/n是转义序列,表示换行符。常见转义序列如下表:
转义序列
含义
/b
退格
/f
换页
/n
换行
/r
回车
/t
跳格
/047
八进制值47,一个单引号
/c
C代表任意其它字符,例如/''
表5.1 转义序列
例子2:
$ nawk '/Sally/{print "/t/tHave a nice day, "$1,$2 "/!"}' employees
Have a nice day, Sally Chang!
解释:如果包含模式Sally,则print函数打印两个跳格,串Have a nice
day,第一个域和第二个域,然后跟叹号。
OFMT变量:当打印数字时,如果使用print函数,想控制精度时,可以
用OFMT变量。默认设置是“%.6g”,也就是打印精度到小数点后6位。下
面的例子可以改变精度。
$ nawk 'BEGIN{OFMT="%.2f"; print 1.23456789,12E-2}'
1.23 0.12
2〉printf函数
printf函数提供了强大的格式化输出功能,如果对c比较熟悉,就不会
感觉太陌生。
转换字符
定义
c
字符
s
串
d
十进制数
ld
长十进制数
u
无符号十进制数
lu
无符号长十进制数
x
十六进制数
lx
长十六进制数
o
八进制数
lo
长八进制数
e
以科学技术发记的符点数
f
浮点数
g
从e或f转换中选择一种占用空间最少的记符点数
表5.2 printf的转换字符
字符
定义
-
左对齐修饰符
#
整数在用八进制显示前面有个0;整数在用十六进制显示时
前面有个0x
+
对于用d、e、f和g的转换,带一个数字符号+或-显示整数
0
显示的值用0补而不是用空格
表5.3修饰符
格式符
功能
假设x=’A’ y=15 z=2.3 $1=Bob Smith
%c
打印一个单ASCII字符
$ printf "The character is %c/n" $x
The character is A
%d
打印一个十进制数
$ printf "The boy is %d years old/n" $y
The boy is 15 years old
%e
打印用科学计数法记的一个数
$ printf "z is %e/n" $z
z is 2.300000e+00
%f
打印一个符点数
$ printf "z is %f/n" $z
z is 2.300000
%o
打印一个数的八进制值
$ printf "y is %o/n" $y
y is 17
%s
打印一个字符串
$ printf "The name of the culprit is %s/n" $1
The name of the culprit is Bob Smith
%x
打印一个数的十六进制值
$ printf "y is %x/n" $y
y is f
表5.4 printf格式说明符
例子:
$ echo UNIX |awk '{printf "|%-15s|/n",$1}'
|UNIX |
解释:echo命令输出从管道中送给awk。格式说明符说明将会打印一个
占15个空格,左对齐,封装在竖杠里而且有换行的串。
$ awk '{printf "The name is %-15s ID is %8d/n",$1,$3}' employees
The name is Tom ID is 4424
The name is Mary ID is 5346
The name is Sally ID is 1654
The name is Billy ID is 1683
4. 在一个文件里的awk命令
如果awk命令放在文件里,就使用-f选项和awk文件名结合使用。处理过程:
把一条记录读到awk的缓存里而且对该记录测试并执行awk文件里的每个命
令。在awk完成对第一条记录的操作后,删除该记录并把下一条记录读入缓
存,依此类推。如果操作不受模式控制,则默认行为是打印整个记录。
例子:
$ cat employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
$ cat awkfile
/^Mary/{print "Hello Mary!"}
{print $1, $2, $3}
$ nawk -f awkfile employees
Tom Jones 4424
Hello Mary!
Mary Adams 5346
Sally Chang 1654
Billy Black 1683
5. 记录和域
1〉记录:awk不把输入数据看作一个无穷的字符串,而是把它看作一种格式
或结构。默认情况下把每行叫做一个记录(record),并以一个换行符终
止。输入和输出的记录分隔符默认是回车符,保存在内置awk变量ORS
和RS中。ORS和RS可以改变,但是方式有限。
例子:
$ nawk '{print $0}' employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
解释:变量$0保存当前记录,这条命令相当于nawk '{print}' employees
例子:
$ awk '{print NR,$0}' employees
1 Tom Jones 4424 5/12/66 543354
2 Mary Adams 5346 11/4/63 28765
3 Sally Chang 1654 7/22/54 650000
4 Billy Black 1683 9/23/44 336500
解释:NR代表行号。
2〉域
类似表中的字段,是指记录中的一个词条。默认域分隔符是空白区域,
也就是空格或制表符(TAB)。Awk中用NF来记录每条记录的域数量。
3〉域分隔符
输入域分隔符:awk的内置变量FS保存输入域分隔符的值。当时用FS
的默认值时,awk用空格或制表符分隔域,删除前导空白区和制表符。FS
可以改变,可以在BEGIN语句中改变,也可以在命令中改变。要想在命
令中改变需要用-F选项。
举例:
$ cat employees2
Tom Jones:4424:5/12/66:543354
Mary Adams:5346:11/4/63:28765
Sally Chang:1654:7/22/54:650000
Billy Black:1683:9/23/44:336500
$ awk '{print $1,$2}' employees2
Tom Jones:4424:5/12/66:543354
Mary Adams:5346:11/4/63:28765
Sally Chang:1654:7/22/54:650000
Billy Black:1683:9/23/44:336500
$ awk -F: '{print $1,$2}' employees2
Tom Jones 4424
Mary Adams 5346
Sally Chang 1654
Billy Black 1683
举例2:多个域分隔符。如果使用多个域分隔符,要将其封装在方括号里。
$ nawk -F'[ :/t]' '{print $1,$2,$3}' employees2
Tom Jones 4424
Mary Adams 5346
Sally Chang 1654
Billy Black 1683
解释:把空格、制表符、冒号当成输入域分隔符。
输出域分隔符:默认的输出域分隔符用逗号来分隔,被分隔的域之间打
印一个空格,如果域之间没有逗号,则打印时各域将挤在一起。
6.模式和操作
awk 模式(patterns)控制awk将对一行输入作什么样的操作。一个模式包括
一个正则表达式,一个产生正确或者错误条件的表达式,或者它们的组合。
默认操作时打印模式中符合表达式条件的各行。当读入一个模式时,有一条
隐含的if语句。如果if语句是隐含的,周围可以没有花括号。
例子:
$ awk '$3<4000' employees
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
解释:如果第3个域小于4000,则打印该域。
操作:操作(actions)是封装在花括号里且由分号分隔的语句。如果一个模式
在一个操作之前,则该模式规定了何时执行该操作。
举例:
$ awk '/Tom/{print "Hello there," $1}' employees
Hello there,Tom
解释:如果记录中包含Tom,则打印Hello there,Tom
7.正则表达式
一个正则表达式对awk来说是一个由封装在正斜杠里的字符组成的模式。Awk
支持的正则表达式与egrep基本一样,可以参考表3.1和表3.2。
举例:
$ nawk '/^Mary/' employees
Mary Adams 5346 11/4/63 28765
解释:显示employees文件中以Mary开头的行
$ nawk '/^[A-Z][a-z]* /' employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
解释:显示行开头是一个大写字母,然后跟一个或多个小写字母,再跟一个
空格。
匹配操作符(~)、否定号(!)用来与以条记录或域里的表达式相匹配。
例子:
$ awk '$1 ~/[Bb]ill/' employees
Billy Black 1683 9/23/44 336500
解释:awk将显示第一个域里与Bill或者bill相匹配的行
$ awk '$1 !~/ly$/' employees
Tom Jones 4424 5/12/66 543354
Mary Adams 5346 11/4/63 28765
解释:显示第一个域中末尾不是ly的所有行。
8.写在命令表文件中的awk命令
写awk命令表的方法可以参考chap05/info文件。该文件内容如下:
# Here is a sample script:
#****************************************************************
*
# My first awk script by Jack Sprat
# Script name: info; Date: February 28, 1999
/Tom/{print "Tom's birthday is " $3}
/Mary/{print NR, $0}
/^Sally/{print "Hi Sally, " $1 " has a salary of $" $4 "."}
#End of script
9.练习题参考答案
习题文件是chap05/donors,部分内容如下:
Mike Harrington 510) 548-1278:250:100:175
Christian Dobbins 40 538-2358:155:90:201
Susan Dalsass 206) 654-6279:250:60:50
Archie McNichol 206) 548-1348:250:100:175
上面的数据库包含名字、电话号码和过去三个月的竞选捐款。
1〉打印所有的电话号码
$ awk -F: '{print $2}' donors
2〉打印Dan的电话号码
$ awk -F: '/^Dan/{print $2}' donors
3〉打印Susan的名字和电话号码
$ nawk -F'[ :/t]' '/^Susan/{print $1,$3,$4}' donors
4〉打印所有以D开头的姓
$ awk '$2 ~/^D/{print $2}' donors
5〉打印所有以一个C或E开头的名
$ awk '/^[CE]/{print $1}' donors
6〉打印所有只有四个字符的名
$ nawk '/^[A-Z][a-z][a-z][a-z] /{print $1}' donors
7〉打印所有那些区号是916的名
$ awk -F: '$2 ~/916/{print $1}' donors
8〉打印Mike的活动捐款。打印每个值时都要以一个美元符号打头;例如:
$500$200$300
$ awk -F: '/^Mike/{printf "$%d$%d$%d/n",$3,$4,$5}' donors
9〉打印姓,其后跟一个逗号和名
$ nawk -F'[ :/t]' '{printf "%s,%s/n",$2,$1}' donors
10〉 写一个叫facts的awk命令表,它能:
a. 打印Savages的全名和电话号码
b. 打印Chet的捐款
c. 打印所有第一个月捐款$250的人
文件内容如下:
$ cat facts
#My first awk scripts by wangzhh.
/Savage/{print $1,$2}
/^Chet/{printf "Beneficence of Chet: $%d$%d$%d/n",$3,$4,$5}
$3 ~/250/{printf " erson who's beneficence is 250:%s/n",$1}
调用方法:
nawk -F: -f facts donors
第6章 awk实用程序:awk编程结构
比较表达式比较行,如果行里的条件为真,就执行操作。如果给表达式求值
为真则值等于1,反之等于0。
1.关系操作符
下表列出了关系操作符。
操作符
含义
例子
<
小于
x<y
<=
小于等于
x<=y
==
等于
x==y
!=
不等于
x!=y
>;=
大于等于
x>;=y
>;
大于
x>;y
~
与正则表达式相匹配
x~/y/
!~
不与正则表达式相匹配
x!~/y/
表6.1关系操作符
关系操作符举例:
$ cat employees
Tom Jones 4423 5/12/66 543354
Mary Adams 5346 11/4/63 28765
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
$ awk '$3==4423' employees
Tom Jones 4423 5/12/66 543354
$ nawk '$3 >;5000{print $1}' employees
Mary
$ nawk '$2 !~/Adam/' employees
Tom Jones 4423 5/12/66 543354
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
条件表达式:一个条件表达式用两个符号,问号和冒号来给表达式求值。与
一个if/else语句相比更简介。
2.条件表达式
格式:
conditional expression1?expression2:expression3
它等同于{if(expression1)
expression2
else
expression3
}
条件表达式举例:
nawk '{max=($1>;$2)?$1 2;print max}' employees
解释:如果第一个域大于第二个域,就把第一个域的内容赋给max,反之把第
二个域的内容赋给max,然后打印max
3.计算
可以在模式里执行计算。awk以浮点方式执行所有的算术运算。
操作符
含义
例子
+
加
x+y
-
减
x-y
*
乘
x*y
/
除
x/y
%
求模
x%y
^
幂运算
x^y
表6.2 算术运算操作符
4.复合模式
复合模式 (compound patterns) 是把模式和逻辑操作符相结合的表达式,给
一个表达式从左到右求值。
操作符
含义
例子
&&
逻辑与
a&&b
||
逻辑或
a||b
!
逻辑非
!a
表6.3 逻辑操作符
复合模式举例:
$ nawk '$3>;4000 && $3<=6000' employees
Tom Jones 4423 5/12/66 543354
Mary Adams 5346 11/4/63 28765
$ nawk '!($3>;4000 && $3<=6000)' employees
Sally Chang 1654 7/22/54 650000
Billy Black 1683 9/23/44 336500
5.范围模式
范围模式从一个模式的第一次出现匹配到第二个模式的第一次出现,然后从
第一个模式的第二次出现匹配到第二个模式的第二次出现等等。如果第一个
模式被匹配,而第二个模式没有找到,则awk将显示直到末尾的所有行。
例子:
$ cat datafile
northwest NW Joel Craig 3.0 .98 3 4
western WE Sharon Kelly 5.3 .97 5 23
southwest SW Chris Foster 2.7 .8 2 18
southern SO May Chin 5.1 .95 4 15
southeast SE Derek Johnson 4.0 .7 4 17
eastern EA Susan Beal 4.4 .84 5 20
northeast NE TJ Nichols 5.1 .94 3 13
north NO Val Shultz 4.5 .89 5 9
central CT Sheri Watson 5.7 .94 5 13
$ nawk '/^north/,/^west/' datafile
northwest NW Joel Craig 3.0 .98 3 4
western WE Sharon Kelly 5.3 .97 5 23
northeast NE TJ Nichols 5.1 .94 3 13
north NO Val Shultz 4.5 .89 5 9
central CT Sheri Watson 5.7 .94 5 13
6.一个数据有效性检查程序
本例子使用chap06/passwd文件,内容如下:
tooth:pwHfudo.eC9sM:476:40:Contract Admin.:/home/rickenbacker/tooth:/bin/csh
lisam:9JY7OuS2f3lHY:4467:40:Lisa M. Spencer:/home/fortune1/lisam:/bin/csh
goode:v7Ww.nWJCeSIQ:32555:60:Goodwill Guest User:/usr/goodwill:/bin/csh
bonzo:eTZbu6M2jM7VA:5101:911: SSTOOL Log account :/home/sun4/bonzo:/bin/csh
info:mKZsrioPtW9hA:611:41:Terri Stern:/home/chewie/info:/bin/csh
cnc:IN1IVqVj1bVv2:10209:41:Charles Carnell:/home/christine/cnc:/bin/csh
bee:*:347:40:Contract Temp.:/home/chanel5/bee:/bin/csh
friedman yuIiKoFTV0TE:3561:50:Jay Friedman:/home/ibanez/friedman:/bin/csh
chambers:Rw7R1k77yUY4.:592:40:Carol Chambers:/usr/callisto2/chambers:/bin/csh
gregc:nkLulOg:7777:30:Greg Champlin FE Chicago
ramona:gbDQLdDBeRc46:16660:68:RamonaLeininge MWA CustomerService Rep:/home/forsh:/bin/csh
要求程序能够显示域个数不等于7的行、第一个域不包含数字字母的行、第
二个域等于星号的行。程序写在ex_6.8.nawk文件中,内容如下:
# nawk script (covered later in the chapter)
# To demonstrate example 6.8 using this script, run
# % nawk -f ex_6.8.nawk passwd
BEGIN {FS = ":"}
NF != 7 { printf("line %d, does not have 7 fields: %s/n",NR,$0)}
$1 !~ /[A-Za-z0-9]/{printf("line %d, nonalphanumeric user id: %s/n"NR,$0)}
$2 == "*" {printf("line %d, no password: %s/n",NR,$0)}
下面是调用方法和执行结果:
$ awk -f ex_6.8.nawk passwd
line 7, no password: bee:*:347:40:Contract Temp.:/home/chanel5/bee:/bin/csh
line 10, does not have 7 fields: gregc:nkLulOg:7777:30:Greg Champlin FE Chicago
7.练习题参考答案
联系文件是chap06下的lab4.data,内容如下:
Mike Harrington 510) 548-1278:250:100:175
Christian Dobbins 40 538-2358:155:90:201
Susan Dalsass 206) 654-6279:250:60:50
Archie McNichol 206) 548-1348:250:100:175
Jody Savage 206) 548-1278:15:188:150
Guy Quigley 916) 343-6410:250:100:175
Dan Savage:(406) 298-7744:450:300:275
Nancy McNeil:(206) 548-1278:250:80:75
John Goldenrod:(916) 348-4278:250:100:175
Chet Main:(510) 548-5258:50:95:135
Tom Savage:(40 926-3456:250:168:200
Elizabeth Stachelin:(916) 440-1763:175:75:300
1>; 打印那些第一个月捐款超过100的人的姓名
$ awk -F: '$3>;100 {print $1}' lab4.data
2>; 打印那些第一个月捐款少于$60的人的姓名和电话号码
$ awk -F: '$3<60{print $1,$2}' lab4.data
3>; 打印那些第三个月捐款在90到150之间的人
$ awk -F: '$5>;=90 && $5<=150 {print $0}' lab4.data
4>; 打印那些三个月捐款在800以上的人
$ awk -F: '$3+$4+$5>;800 {print $0}' lab4.data
5>; 打印那些平均每月捐款大于$150的人名和点话号码
$ nawk -F'[ :/t]' '($5+$6+$7)/3>;150{print $1,$3,$4}' lab4.data
6>; 打印那些区号不是916的人名
$ nawk -F'[ :/t]' '$3 !~/916/{print $1}' lab4.data
7>; 打印每条记录,记录号在前面
$ awk '{print NR,$0}' lab4.data
8>; 打印每个人的名字和捐款总额
$ nawk -F'[ :/t]' 'sum=($5+$6+$7) {print $1,sum}' lab4.data
9>; 把Elizabeth的第二次捐款加上$10
$ nawk -F'[ :/t]' 'juankuan=($1 ~/Elizabeth/)?$6+10 6{print $1,juankuan}' lab4.data
10>;把Nancy McNeil的名字改成Louise McInnes
$ nawk 'name=($1 ~/Nancy/)?"Louise McInnes" 1{print name}' lab4.data
第7章 awk实用程序:awk编程
1.变量
.. 数值和串常数
数值常数可以表示成整数、浮点、科学计数等。含有空格的串要封装在
双引号里。例如"Hello world"。如果一个域或这数组元素为空,则串值
为空。一个空行也被当作空串。
.. 用户自定义变量
用户自定义变量包括字母、数字和下划线,且不能以数字开头。在awk
中变量不用声明,awk通过表达式的上下文推断变量类型,并且如果需
要,还可以在不同类型的变量中相互转换。
.. 递加和递减操作符(++和--)
与c++语言中一样。x++是后递加,++x是先递加。
.. 内置变量。
内值变量要大写,他们可以用在表达式里而且可以被重置。如下表
变量名
含义
ARGC
命令行变元个数
ARGV
命令行变元组数
FILENAME
当前输入文件名
FNR
当前文件里的记录号
FS
输入域分隔符,默认是空格
NF
当前域里的域个数
NR
到目前为止的记录数
OFMT
数值输出格式
OFS
输出域分隔符
ORS
输出记录分隔符
RLENGTH
由match函数匹配的串的长度
RS
输入记录分隔符
RSTART
由match函数匹配的串偏移量
SUBSEP
下标分隔符
表7.2 nawk内置变量
内置变量举例:
$ nawk -F: '$1=="Mary Adams"{print NR,$1,$2,$NF}' employees2
2 Mary Adams 5346 28765
解释:-F选项把分隔符改成冒号。如果域1等于Mary Adams,则打印记
录号、第一个域、第二个域和最后一个域($NF)
.. BEGIN模式
BEGIN模式后面跟一个操作模块,在awk处理文件之前执行该模块。BEGIN
模式主要用来设置OFS、RS、FS等内置变量的值。
$ awk 'BEGIN{FS=":";OFS="/t";ORS="/n/n"}{print $1,$2,$3}' employees2
Tom Jones 4423 5/12/66
Mary Adams 5346 11/4/63
Sally Chang 1654 7/22/54
Mary Black 1683 9/23/44
解释:在处理输入文件之前,把域分隔符置成一个冒号,输出域分隔符
制成跳格符,并把输出记录分隔符(ORS)设置成两个换行符。
.. END模式
END模式不与任何输入行相匹配,但是执行任何与END模式相关的操作。
在所有行处理完毕之后再来处理END模式。
$ awk '/Mary/{count++}END{print "Mary was found " count " times."}' employees
Mary was found 1 times.
解释:对于包含Mary的每一行,count变量值都递增1。awk 处理完毕之
后,END模块打印结果。
2.重定向和管道
.. 输出重定向:当把输出从awk重定向到一个UNIX文件时,使用shell
重定向操作符。如果重定向操作符用在awk命令里面则必须将重定向文
件用双引号括起来。例如:
$ awk '$4>;70 {print $1,$2 >;"passing_film"}' datafile
.. 输入重定向(getline)
getline 函数用来从标准输入,例如管道或者文件来读入数据,而不是
从正被处理的当前文件。getline 取得输入的下一行,并更新NF、NR
和FNR等内置变量的值。如果getline找到记录则返回1,达到EOF(文
件结束)则返回0。如果有错误则返回-1。
.. 举例1:
$ nawk 'BEGIN{"date"|getline d;print d}' datafile
2005年05月06日 星期五 15时05分41秒 CST
解释:执行date命令,然后把输出从管道送到getline,并赋给自
定义变量d,然后打印d。
.. 举例2:
$ nawk 'BEGIN{while("ls"|getline) print}'
awk.sc2
datafile
datafile2
employees
employees2
lab5.data
names
passwd
解释:将把ls的输出送到getline。对于每次循环,getline都从
ls读取一个以上输出,然后打印到屏幕上
.. 举例3:
$ nawk 'BEGIN{printf "What is your name?";/
>; getline name<"/dev/tty"}/
>; $1 ~ name {print "Found " name " on line ",NR "."}/
>; END{print "See ya, " name "."}' employees
What is your name?Wangzhonghai
See ya, Wangzhonghai.
解释:将在屏幕上打印What is your name?,并且等待用户响应。
getline 函数将从终端(/dev/tty)接受输入,一直到输入一个换行
符为止,然后把输入存到用户自定义变量name中。如果递一个域和
name的值相匹配,则执行print函数。在END模式中打印”See ya,”
然后跟name的值。
.. 举例4
$ nawk 'BEGIN{while (getline<"/etc/passwd">;0)lc++;print lc}'
16
解释:awk将从“/etc/passwd”读取各行,lc递增,直到EOF,然
后打印lc的值。
3.管道
如果在一个awk程序中打开一个管道,则必须在打开另一个之前先关闭它。
在管道符号由变的命令封装在双引号里。一次只能打开一个管道。下面的例
子是将names文件中的姓名按照姓作为第一关键字,名作为第二关键字来进
行倒排序:
$ awk '{print $1,$2|"sort -r +1 -2 +0 -1 "}' names
tony tram
john smith
dan savage
barbara nguyen
elizabeth lone
john goldenrod
susan goldberg
george goldberg
eliza goldberg
alice cheba
4.关闭文件和管道
如果在awk中再次使用一个文件或者管道来读取或写入,则需要首先关闭管
道。打开和关闭管道的例子可以参考/chap07/awk.sc3文件。(书中源代码没
有这个文件,而书上错误很多。)
5.回顾(略)
6.条件语句
1) if 语句
以if结构开头的语句是操作语句。在条件模式(conditional patterns)
里,if是隐含的;在一个条件操作语句中,if要显式说明,并且后面跟
一个封装在括弧里的表达式。如果跟在条件表达式后面的语句不止一条,
则语句组必须放在花括号里,并且用分号或者换行符来分开。
格式:
if (expression){statement;statement;…}
举例1:
$ nawk '{if($8>;15) print $1 " To high"}' datafile
举例2:
$ nawk '{if($8>;15 && $8<=23){safe++; print $1 " OK " safe}}' datafile
2) if/else语句
if/else语句允许一个二路判断。
格式:
{if(expression) {
statement;statement;…
}
else{
statement;statement;…
}
}
3) if/else else if语句
允许多路判断。
格式:
{if (expression) {
statement;statement;…
}
else if (expression){
statement;statement;…
}
else if (expression){
statement;statement;…
}
else{
statement;statement;…
}
}
7.循环
循环的作用是,如果一个条件为真,则重复执行测试表达式后的语句。循环
通常用来迭代一条记录里的域,及循环操作END模块里的一个数组的元素。
awk 有3种循环:while循环、for循环和特殊for循环。
1) while循环
使用规则与c中一样。
举例:
$ nawk '{i=1;while(i<=NF){print NF,$i;i++}}' datafile
解释:变量i初始化为1;当I小于或等于记录中的域个数(NF)时,执行
print并让i递增,然后再测试表达式,直到i>;NF。读取下一条的记录的
时候i被重新初始化。
2) for循环
使用规则与c中一样。
举例:
$ nawk '{ for (i=1;i<=NF;i++) print NF,$i}' datafile
3) 循环控制:break和continue
break 和 continue。break 让你在某个条件为真时调出循环。continue
使循环在某个条件为真时条过后面的任何语句,并把控制返回循环顶部,
开始下一次迭代。
举例:
{for (x=3;x<=NF;x++)
if($x<0){print "Bottomed out!";break}
#breaks out of for loop
}
举例2:
{for (x=3;x<=NF;x++)
if($x==0){print "Get next item!";continue}
#starts next item of for loop
}
8.程序控制语句
1) next 语句
next 语句从输入文件取得下一个输入行,在awk命令表顶部重新开始执
行。
举例:
$ awk '{if($1 ~/Tom/){next} else {print}}' db
解释:如果第一个域包含Tom,则略过。
2) exit语句
exit 语句用来终止awk程序。它停止处理记录,但是不跳过END语句。
3)
9.数组
在awk中数组叫做关联数组(associative arrays),因为下标记可以是数也
可以是串。awk中的数组不必提前声明,也不必声明大小。数组元素用0或
空串来初始化,这根据上下文而定。
1) 关联数组的下标
.. 把变量用作数组索引。
举例:
$ nawk '{name[x++]=$2};END{for(i=0;i<NR;i++)/
>; print i,name }' employees
0 Jones
1 Adams
2 Chang
3 Black
解释:在数组name里的下标是一个用户自定义变量x。++显示了一个
数值型的上下文。
.. 特殊for循环
在for循环无效的情况下,即当串被用作下标或者下标不是连续的数
时,用特殊for循环来读取一个关联数组。特殊for循环把下标当作
一个键来找到它的相关的值。
格式:
{for(item in arrayname){
print arrayname[item]}}
举例:
$ nawk '/^Tom/{name[NR]=$1};/
>; END{for(i=1;i<=NR;i++) print name}' db
Tom
Tom
Tom
Tommy
$ nawk '/^Tom/{name[NR]=$1};/
>; END{for(i in name){print name}}' db
Tom
Tom
Tommy
Tom
解释:这两个例子用NR(行号)来做下标,因此匹配Tom的模式的行
不连续,数组下标不连续。如果用传统for来循环打印会在数组没有
值的地方打印空值。通过使用特殊for循环,只打印数组中有值的内
容。
..
2)
10.
附录B 比较三种shell
特性
C shell
Bounne shell
Korn shell
变量
给局域变量赋
值
set x=5
s=5
s=5
赋变量属性
typeset
给环境变量赋
值
setenv NAME Bob
NAME=Bob
export NAME=Bob
存取变量
echo $NAME
set var=net
echo ${var}work
network
echo $NAME
var=net
echo ${var}work
network
echo $NAME或print
$NAME
var=net
print ${var}work
network
专用
变量
该进程的PID
$$
$$
$$
退出状态
$status
$?
$?
上一个后台作
业
$!
$!
数组
给数组赋值
Set x=(a b c)
N/A
Y[0]=a;y[1]=b;y[2]=c
Set –A fruit apples
pears plums