Shell精解

简介:

第一章 关于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 wpg 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/)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则匹配 

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行。书中解释有误。 
第3章 grep家族 
1.grep的含义是“全局搜索正则表达式(RE)并打印该行” 
2.grep支持的正则表达式 和在文档中搜索基本相同。能够参考表2.1。 
3.grep 的选项 功能 
-b 在各行之前放置他发现的块号。有时在根据上下文定位磁盘字块时有用
-c 显示匹配行数而不是内容 
-h 不显示文档名 
-I 在座比较时忽略字母大小写 
-n 文档中每行之前给出他的相关行号 
-s 无声操作。即除了错误消息外不做任何显示。用于检查退出状态 
-v 把搜索翻转为只显示不匹配的行 
-w 把表达式当作一个次来搜索,相当于用/;括起来 

4.grep命令的退出状态 
假如grep操作成功,则状态是0,假如模式没找到,状态是1,假如文档没找到,状态是2。假如操作被取消,则状态是130。查看状态的方法:在csh中用echo $status。在sh和ksh中用echo $? 。
例如 $ echo $? 

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匹配 

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;THE NORTH SALES DISTRICT HAS MOVED;THE NORTH SALES DISTRICT HAS MOVED;THE NORTH SALES DISTRICT HAS MOVED; 插入:i命令 
$ sed '/north/i/ 
>; ---->;THE NORTH SALES DISTRICT HAS MOVED;THE NORTH SALES DISTRICT HAS MOVED;THE NORTH SALES DISTRICT HAS MOVED;THE NORTH SALES DISTRICT HAS MOVED;下一个: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函数 
$ 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代表任意其他字符,例如/'' 
例子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转换中选择一种占用空间最少的记符点数 
- 左对齐修饰符 
# 整数在用八进制显示前面有个0;整数在用十六进制显示时前面有个0x 
+ 对于用d、e、f和g的转换,带一个数字符号+或-显示整数
0 显示的值用0补而不是用空格 
假设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 
$ 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将对一行输入作什么样的操作。一个模式包括1个正则表达式,一个产生正确或错误条件的表达式,或他们的组合。默认操作时打印模式中符合表达式条件的各行。当读入一个模式时,有一条隐含的if语句。假如if语句是隐含的,周围能够没有花括号。 
例子: 
$ awk '$3;= 
大于等于 x>;=y 
>; 大于 x>;y 
~ 和正则表达式相匹配 x~/y/ 
!~ 不和正则表达式相匹配 x!~/y/ 
关系操作符举例: 
$ 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 
4.复合模式 
复合模式 (compound patterns) 是把模式和逻辑操作符相结合的表达式,给一个表达式从左到右求值。 
操作符 
&& 逻辑和 a&&b 
|| 逻辑或 a||b 
! 逻辑非 !a 
复合模式举例: 
$ nawk '$3>;4000 && $3;4000 && $3; 打印那些第一个月捐款超过100的人的姓名 
$ awk -F: '$3>;100 {print $1}' lab4.data 
2>; 打印那些第一个月捐款少于$60的人的姓名和电话号码 
$ awk -F: '$3; 打印那些第三个月捐款在90到150之间的人 
$ awk -F: '$5>;=90 && $5; 打印那些三个月捐款在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 
第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; $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;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文档。(书中源代码没有这个文档,而书上错误很多。) 
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;NF。读取下一条的记录的时候i被重新初始化。 
2) for循环 使用规则和c中相同。 
举例: 
$ nawk '{ for (i=1;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 in name){print name}}' db        ::::::不同的内核有不同的写法,不要硬套
Tom 
Tom 
Tommy 
Tom 
解释:这两个例子用NR(行号)来做下标,因此匹配Tom的模式的行不连续,数组下标不连续。假如用传统for来循环打印会在数组没有值的地方打印空值。通过使用特别for循环,只打印数组中有值的内容。 

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) 
Y[0]=a;y[1]=b;y[2]=c
Set –A fruit apples pears plums

相关文章
|
4月前
|
Java Shell Linux
shell(一)shell编程入门
开始学习shell编程之前,我先啰嗦几句,作为一个web开发工作者,在部署网站的时候不可避免的要使用linux服务器。 对于大部分同学来说,配置linux服务器的环境是一件很难的事情,包括刚开始接触linux的我也是一样的。 最开始的时候也是碰到了不少坑,走了很多弯路。后来有了第一篇关于服务器环境配置的教程《Centos7.6配置lnmp》关于这篇教程纯粹就是我一点一点试出来的。在百度上各种查,把好用的部分整理在了一起。里边也包含了很多东西,包括yum的配置,nginx的配置文件编写。以上的东西,惭愧点说,我是看不懂的。反正好用了就行了呗。
33 1
|
8月前
|
Shell
如何学好shell
如何学好shell
46 0
|
10月前
|
机器学习/深度学习 运维 JavaScript
Linux运维之初识shell
Linux运维之初识shell
|
机器学习/深度学习 缓存 安全
|
运维 Java Shell
Shell 脚本编程基础|学习笔记
快速学习 Shell 脚本编程基础.
114 0
|
存储 Ubuntu Java
Shell笔记(超级完整)
Shell笔记(超级完整)
Shell笔记(超级完整)
|
Shell
shell笔记
一:exit(0)与exit(1)、return区别        exit函数是退出应用程序,删除进程使用的内存空间,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息,这个信息和机器和操作系统有关,一般是 0 为正常退出, 非0 为非正常退出。
1208 0