1、 《实用UNIX教程》中的例题 第101页 共101页 教材 《实用UNIX教程》 第1章 UNIX简介 【例1-1】使用telnet登录到远程一台AIX系统的例子。 括号内的楷体字内容是一些注释。 $ (在shell提示符下输入命令) $ telnet 202.172.122.135 Trying... Connected to 202.172.122.135. Escape character is '^]'. AIX Version 5 (C) Copyrights
2、 by IBM and by others 1982, 2000. login: jiang (出现登录提示符,输于远程计算机用户的用户名/口令) jiang's Password:*** ********************************************************** * Welcome to AIX Version 5.1! * Please see the README file in /usr/lpp/bos for information * pertinent to this release of t
3、he AIX Operating System. ********************************************************** Last unsuccessful login: Wed Jun 25 12:38:45 2003 on /dev/pts/0 from 61.149.71.89 Last login: Wed May 19 08:04:53 2004 on /dev/pts/0 from 61.149.159.49 $ (登录到了远程的计算机,这里的shell提示符$是远程计算机给出的,在此输入的命令,在远程计算机上执行)
4、 $ tty /dev/pts/1 $ who am i jiang pts/1 May 19 08:45 $ $ ^](在此按下转义字符Ctrl-]键,会出现telnet的提示符,开始和本地telnet仿真程序会话) telnet> help Commands may be abbreviated. Commands are: close close current connection display display operating parameters emulate emulate a vt100 or 3270 termi
5、nal mode try to enter line-by-line or character-at-a-time mode open connect to a site quit exit telnet send Transmit special characters ('send ?' for more) set set operating parameters ('set ?' for more) status print status information toggle toggle operating parameters ('to
6、ggle ?' for more) z suspend telnet ? print help information telnet> (在此直接按回车,退出和telnet程序的会话,继续与远程计算机会话) $ tty /dev/pts/1 $ $ exit Connection closed. 【例1-2】ftp会话的过程。 $ ftp 202.162.120.115(在shell中输入ftp命令). Connected to 202.162.120.115. 220 RISC6000 FTP server (Version wu-2.6.1(
7、1) Thu Jul 20 19:10:14 DFT 2000) ready. Name (jiang): jiang(输入远程计算机的用户名和口令) 331 Password required for jiang. Password:*** 230 User jiang logged in. ftp> dir(在ftp>提示符下,可以输入ftp的命令,dir用于察看远端计算机的目录) 200 PORT command successful. 150 Opening ASCII mode data connection for /bin/ls. total 522776
8、rw----r-- 1100 328 Aug 30 2003 .sh_history -rw-r--r-- 1100 181248 Sep 9 2003 paper01.txt -rw-r--r-- 1100 996987 Sep 28 2003 paper02.txt -rw-r--r-- 1100 27703298 Mar 13 2003 linux-2.4.tar -rw-r--r-- 1100 27699283 Apr 9 02:13 linux.tar.Z -rw-r--r-- 1100 207575995 May 13 22:55 books.tar.Z -rw-
9、r--r-- 1100 992094 Sep 9 2003 src.tar.Z 226 Transfer complete. ftp> help(输入help命令,打印出ftp的所有命令列表) Commands may be abbreviated. Commands are: ! image recv $ lcd reget account local
10、reinitialize ...(省略) ftp> get src.tar.Z (get命令将远程计算机的文件传到本地) 200 PORT command successful. 150 Opening ASCII mode data connection for src.tar.Z (992094 bytes). 226 Transfer complete. 995934 bytes received in 0.4596 seconds (2116 Kbytes/s) local: src.tar.Z remote: src.tar.
11、Z ftp> ftp> put myfile(put命令将本地计算机的文件传到远程主机) 200 PORT command successful. 150 Opening ASCII mode data connection for myfile. 226 Transfer complete. 995934 bytes sent in 0.2397 seconds (4057 Kbytes/s) local: myfile remote: myfile ftp> bye(bye命令退出ftp) 221-You have transferred 1988028 bytes i
12、n 2 files. 221-Total traffic for this session was 1989427 bytes in 3 transfers. 221 Goodbye. 有些ftp服务器,允许匿名登录。匿名登录时,使用用户名anonymous,口令输入时应当输入自己的E-mail地址,有的系统允许随意输入,或者不问口令。 【例1-3】ftp使用二进制方式传输文件的例子。 ftp> binary 200 Type set to I. ftp> get A301211.JPG 200 PORT command successful. 150 Op
13、ening BINARY mode data connection for A301211.JPG (805603 bytes). 226 Transfer complete. 805603 bytes received in 0.2035 seconds (3865 Kbytes/s) local: A301211.JPG remote: A301211.JPG 【例1-4】cal命令用法举例。 cal 打印当前月份的日历。 cal 2005 打印2005年的日历。 cal 10 2006 打印 2006年10月份的日历。 根
14、据命令的语法,要想指定月份,必须指定年份。命令cal 12,系统会以为要打印出公元12年全年的日历,而不是打印今年12月的日历。 $ cal May 2004 Sun Mon Tue Wed Thu Fri Sat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 $ cal 2005
15、 2005 January February Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat 1 1 2 3 4 5 2 3 4 5 6 7 8 6 7 8 9 10 11 12 9 10 11 12 13 14 15 13 14 15 16 17 18 19 1
16、6 17 18 19 20 21 22 20 21 22 23 24 25 26 23 24 25 26 27 28 29 27 28 30 31 . . . November December Sun Mon Tue Wed Thu Fri Sat Sun Mon Tue Wed Thu Fri Sat 1 2 3
17、 4 5 1 2 3 6 7 8 9 10 11 12 4 5 6 7 8 9 10 13 14 15 16 17 18 19 11 12 13 14 15 16 17 20 21 22 23 24 25 26 18 19 20 21 22 23 24 27 28 29 30 25 26 27 28 29 30 31 $ cal 10 2006 October 20
18、06 Sun Mon Tue Wed Thu Fri Sat 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 【例1-5】使用bc命令的例子。 其中的圆括号内的楷体字提示使用bc时的注意事项。 $ bc (启动bc命令) 18 * (5 + 5) (输入一个表达式,表达式中可以使用括号) 180 (打印出表达式的计算结果) 1024 * 4096
19、4194304 (下边是一个高精度计算的例子。在32位系统中,数据线宽度32比特,CPU一次可运算的最大整数是4G,这也是C语言中无符号整数的最大值,下边的两个数以及它们的乘积都超过了4G) 1234567890123456789012345 * 9876543210987654321098765 12193263113702179522618496034720321071359549253925 2.5 * 2.1 (浮点数运算) 5.2 (运算结果应当是5.25,但是由于精度太低,未能取得期望的值) 1/113 0 (浮点数运算结果的
20、精度太低,未能取得期望的值) scale=40 (上述语句设置bc的内部控制变量,使得计算结果可保留到小数点后40位。很糟糕,scale的默认值为零,才有上述两次计算结果的不如意) 2.5 * 2.1 5.25 (重新计算,得到正确结果) 1/113 .0088495575221238938053097345132743362831 (运算结果是无限循环小数,保留40个小数位) (在这里按下Ctrl-D键,退出bc程序,返回shell,出现shell提示符) $ $ bc -l (使用bc命令带-l选项, bc的内部控制变量scale自动被设置为20,再
21、进行浮点运算2.5*2.1或1/113会得到期望的结果,期望保留更多的小数位数,可以自行设置scale控制变量。-l选项原意是library,定义了一个bc使用的任意精度的数学函数库,包括正弦函数s(x),余弦函数c(x)等,另外,将scale初始设置为20) 2.5 * 2.1 5.25 1/113 .00884955752212389380 p = 2.346901 (bc允许使用a~z的26个寄存器,后边的计算如果经常使用这个值,将它存入到寄存器p中) 17.8 * p 41.7748378 198.23 * p 465.22618523
22、 $ 在使用浮点数运算的时候,最好直接使用bc –l选项。有关bc命令的更丰富功能,可参阅命令手册。 第2章 基本UNIX实用程序 【例2-1】使用od命令的例子。 $ od a.dat 0000000 046532 131400 004000 000000 020000 000153 016220 002000 0000020 000400 051571 071564 062555 020126 062562 071551 067556 0000040 020064 027071 030015 005044 075007 000016 017570 00463
23、0 0000060 020533 000514 036441 000000 000000 056011 000000 004000 0000100 000000 000000 000000 005000 000000 047105 002474 107510 0000120 072025 002035 007566 007152 062000 (最左列以十六进制形式指出数据在文件中的偏移量) $ od -c a.dat 0000000 M Z ? \0 \b \0 \0 \0 \0 \0 k 034 220 004 \0 0000
24、020 001 \0 S y s t e m V e r s i o n 0000040 4 . 9 0 \r \n $ z \a \0 016 037 x \t 230 0000060 ! [ 001 L = ! \0 \0 \0 \0 \ \t \0 \0 \b \0 0000100 \0 \0 \0 \0 \0 \0 \n \0 \0 \0 N E 005 < 217 H 0000120
25、 t 025 004 035 017 v 016 j d (从这里能看到,文件中有System Version字符串) $ od -x a.dat 0000000 4d5a b300 0800 0000 2000 006b 1c90 0400 0000020 0100 5379 7374 656d 2056 6572 7369 6f6e 0000040 2034 2e39 300d 0a24 7a07 000e 1f78 0998 0000060 215b 014c 3d21 0000 0000 5c09 0000 0800 0000100 0000
26、0000 0000 0a00 0000 4e45 053c 8f48 0000120 7415 041d 0f76 0e6a 6400 $ echo abcdABCD | od –x 0000000 6162 6364 4142 4344 0a00 $ 【例2-2】使用head和tail命令的例子 $ head -15 ab.c (显示文件ab.c中前15行) $ head -23 a.c b.c c.c | more (显示三个文件各自的前23行共显示69行) $ tail -20 liu.mail (打印出文件尾部的20行,看看
27、邮件尾部的发信者签名) $ netstat –s –p tcp | head -5 tcp: 5902873 packets sent 5118107 data packets (3423705271 bytes) 35445 data packets (18222213 bytes) retransmitted 329697 ack-only packets (35578 delayed) 【例2-3】使用tail命令实时显示文件新追加的内容。 tail –f /usr/adm/pppd.log 【例2
28、4】使用wc命令的例子。 wc sum.c (1个文件) wc x.c makefile stat.sh (多个文件) 以下是上机操作实例。 $ wc *.[ch] makefile *.sh 1912 6532 49143 auth.c 1227 4038 32394 ccp.c 860 2558 22487 chap.c 124 695 4702 chap.h 762 2129 17159 fsm.c 144 792 5237 f
29、sm.h 2168 7487 56500 lcp.c 87 288 2035 magic.c 1827 5833 44234 main.c 306 1901 11841 md5.c 58 349 3048 md5.h 390 1343 9138 multilink.c 1545 5220 37149 options.c 738 4142 28320 pppd.h 876 2712 18623 utils.c 347 1324 9673 makefile 78 735 5
30、125 ppp.sh 13449 48078 356808 total $ ps –ef | wc -l 108 $ who | wc -l 10 【例2-5】使用sort命令的例子。 $ ls -s | sort | tail –10 (默认的按照字符串方式比较进行排序) 44 main.c 48 auth.c 56 lcp.c 1268 BUGS.report 1720 paper.pdf 202712 document.pdf 27052 disk.img 27056 linux-src.tar.Z 3532 pppd.l
31、og total 263724 $ ls -s | sort -n | tail –10 40 options.c 44 main.c 48 auth.c 56 lcp.c 1268 BUGS.report 1720 paper.pdf 3532 pppd.log 27052 disk.img 27056 linux-src.tar.Z 202712 document.pdf 【例2-6】正则表达式中符号*的作用。 (1) 正则表达式12*4 1234 不匹配 1224 匹配 12224 匹配 14 匹配
32、此例中*作用于它左面的单字符正则表达式2。注意正则表达式12*4与字符串14是匹配的。 (2) 正则表达式[A-Z][0-9]* 此例中*作用于它左侧的单字符正则表式为[0-9],代表: [A-Z] [A-Z][0-9] [A-Z][0-9][0-9] [A-Z][0-9][0-9][0-9] …… 与A,A1,C45,D768匹配,与b64512,T546t不匹配 (3) 正则表达式[Cc]hapter *[1-4] 在*号前有一个空格,允许数字
33、1-4之前有多个或者0个空格。可匹配Chapter2, chapter 3,等等。类似的,正则表达式: a\[i] *= *b\[j] *\* *c\[k] 可以匹配字符串a[i]=b[j]*c[k],并允许等号和星号两侧有多个或者0个空格。 【例2-7】正则表达式中$和^的作用。 (1) 123$ 则匹配文件中行尾的123,不在行尾的123字符与正则表达式123$不匹配。 (2) $123与字符串$123匹配 (3) .$匹配行尾的任意字符。 (4) 正则表达式^Hello匹配行首的Hello字符串,不在行首的Hello串不匹配
34、 (5) 正则表达式Hel^lo与字符串Hel^lo匹配。 (6) ^号后跟四个空格,那么,仅匹配行首的连续4个空格。 【例2-8】grep命令的使用。 grep O_RDWR /usr/include/*.h 用于查找C语言中宏定义O_RDWR在哪些头文件中定义,查找范围为多个文件。类似的命令用于查找C语言的struct类型定义,等等。 grep routed /etc/tcp 指定文件数=1 who | grep liang 指定的文件数=0 【例2-9】egrep的扩展正则表达式的使用。 eg
35、rep可以使用扩展的正则表达式,下面是几个扩展正则表达式以及他们可以匹配的字符串示例。 (xy)* 可匹配空字符串,xy,xyxy,xyxyxy,等等。 (pink|green) 与pink或green匹配。 [0-9]+ 不匹配空字符串,匹配长度至少为一数字串。 a? 匹配零个或一个a。 下面的两个命令按扩展的正则表达式规则检索字符串。 egrep '(SEEK_|IPC_)' *.h egrep '[0-9]:[0-9][0-9] (client|server)$' egrep在指定模式方面比grep更灵活,但算法需要稍多的处理时间。
36、 【例2-10】grep选项的使用。 (1)grep -n __DATE__ *.c 在所有的后缀为.c的文件中查找含有正则表达式__DATE__的行,并打印行号。当文件数超过一个时,除了输出行号,还输出文件名。 (2) grep -v '[Dd]isable' device.stat>device.active 将文件device.stat中取消所有含有指定模式的行,生成新文件device.active。 (3) grep -i richard telnos 在文件telnos中检索字符串richard,不顾字母的大小写。
37、 (4) grep '[0-9]*' chapter1 由于[0-9]*与空字符串匹配,上述命令打印出chapter1文件中所有行,而不是仅打印出含数字的行。正确的用法应当是:grep '[0-9][0-9]*' chapter1。 打印出文件chapterl中所有含有数字的行。或者使用egrep的扩展正则表达式: egrep '[0-9]+' chapter1 【例2-11】使用awk命令的例子。 $ date Thu May 27 22:02:22 BEIDT 2004 $ date | awk '{print $4}' (未指定条件,处理
38、所有的文本行) 22:02:42 $ who zhang ttylb Sep 29 11:20 liang ttyla Sep 29 11:53 zhang ttylf Sep 29 12:04 feng tty1c Sep 29 12:54 $ who | awk '/^ *zhang / {printf("%s ", $2)}' (仅处理含有正则表达式zhang字符串的文本行。由于printf的格式字符串尾不含\n,程序执行完之后,不换行,导致下个命令的提示符$在打印行的行尾) tty1b tty1f $ $ ls -s
39、 awk '$1 > 2000 { print $2 }' (这里的描述条件为:第一列的取值大于2000的文本行) disk.img document.pdf linux-src.tar.Z pppd.log $ cat list.awk (事先编辑好的awk程序文件,程序中含有三组“条件 {动作}”描述。其中:BEGIN的动作有三个,程序执行时,awk处理所有文本行之前,执行BEGIN指定的三个动作;处理完所有文本行之后,执行END指定的一个动作;最后一个程序块,未指定任何条件,对所有文本行执行这个动作。在这段程序中使用了内置变量FILENAME和NR, $0) BEG
40、IN { printf("=====================================\n") printf("FILENAME %s\n", FILENAME) printf("-------------------------------------\n") } END { printf("====================================\n") } { printf("%3d: %s\n", NR, $0) } $ awk -f list.awk md5.c ===================
41、 FILENAME md5.c ------------------------------------- 1: 2: #include "md5.h" 3: 4: /* forward declaration */ 5: static void Transform (); 6: 7: /* F, G, H and I are basic MD5 functions */ 8: #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) …… 298: buf[
42、2] += c; 299: buf[3] += d; 300: } 301: ==================================== 【例2-12】使用sed命令的例子。 (1) tail -f pppd.log | sed 's/145\.37\.123\.26/QiaoXi/g' sed的编辑命令有很多,这里的s命令是“替换(substitute)”,三个斜线分割的第一部分是正则表达式145\.37\.123\.26,第二部分是替换字符串QiaoXi,最后的g是global flag,这一特征字符,使得s命令在一行中遇到多个模式描
43、述的字符串时,都替换为QiaoXi,否则,仅替换一次。 上述命令中,sed将IP地址转为一个名字。 (2) tail -f pppd.log | sed -f sed.script 其中sed.script文件内容如下: s/145\.37\.123\.26/QiaoXi/g s/102\.157\.23\.109/LiuYin/g s/145\.37\.123\.57/DaTun/g …… 使用这样的方法,定义一张IP地址/名字的对照表,sed可以将一些程序的输出内容进行编辑替换,加工之后再显示出来。 【例2-13】使用tr命令的例子
44、 (1) 将大写UVX改写为小写uvx。 cat telnos | tr UVX uvx (2) 可以使用[ ]指定一个集合。 cat report | tr '[a-z]' '[A-Z]' 将小写字母改为大写字母。 (3) 也可以使用\加三个八进制数字(类似C语言中描述字符常数的方法)表示一个字符。下面的命令将%改为换行符: cat file1 | tr % '\012' 在第一章1.3.5节中介绍过UNIX和DOS文本文件的区别,下面的命令将按照二进制格式从DOS拷贝来的文件中多余的回车改为
45、空格,回车的ASCII码是八进制的015。 cat myap.c | tr '\015' ' ' > myap1.c 这几个例子的命令中,注意不要漏掉必需的单引号。 【例2-14】 比较两个不同版本的C语言源程序文件,找出文件的改动之处。 源程序文件f1.c被修改后的新版本源程序文件为f2.c,下面是UNIX下比较两个文本文件f1.c和f2.c的结果。 $ cmp f1.c f2.c f1.c f2.c differ: char 69, line 3 $ diff f1.c f2.c 3,5d2 < tmp->vm_mm = mm; < mm
46、>map_count++; < tmp->vm_next = NULL; 260c257 < i = (i+1) * 8 * sizeof(long); --- > i = i * 8 * sizeof(long); 528c525 < p->swappable = 1; --- > p->swappable = 0; 548a546,547 > retval = p->pid; > p->tgid = retval; 第3章 全屏幕编辑程序vi 【例3-1】 将abc字符串替换为xyz。 :1,50s/abc/
47、xyz/ 将第1-50行的字符串abc换为xyz,如果同一行内有多个abc字符串,则只替换第一个。 :1,50s/abc/xyz/g 将第1-50行的字符串abc换为xyz,如果同一行内有多个abc字符串,则替换所有的abc字符串。 :s/abc/xyz/g 仅将当前行的字符串abc换为xyz,如果当前行中有多个abc字符串,则替换所有的abc字符串。 【例3-2】在编辑C语言源程序时,把一部分行右移/左移四列。 :50,80s/^/ /g 这样,在50~80行的行首增加了四个空格,从
48、效果上看,第50~80行右移4列。 :50,80s/^ //g 这样,在50~80行的行首的四个空格被替换成空字符串,从效果上看,第50~80行左移4列(每行首部必须有四个空格)。 ② 模式描述使用正则表达式 使用替换命令时应特别注意在描述模式时使用的是正则表达式,尤其是在编辑C语言源程序时,不要忘记在应该加转义符时加上转义符。下面的例子中的转义符\是必不可少的。 【例3-3】注意vi替换命令中用于模式描述的正则表达式中的特殊字符。 (1) 将end.改为middle.。 :1,$s/end\./mid
49、dle./g 指定范围为从第一行到最后一行,就是在整个文件中替换。middle后边的圆点前不需要加反斜线。这里的middle.是替换字符串,不是正则表达式,圆点就没有任何特殊含义,因此不能在它前边加反斜线。 (2) 删除每行尾部的一个字符。 :1,$s/.$//g 将Windows中的文本文件按照二进制格式拷贝到Unix系统中,由于两种系统文本文件存储格式上的差异,在UNIX看来每行尾部都多余一个ASCII码为13的字符,在vi显示的时候,每行尾部显示一个^M,使用上述的命令,将行尾的一个字符替换为空字符串,就可以将行尾的^M消除。但使用
50、1,$s/\^M//g不能达到目的。 (3) 将a[i]*b[j]替换为x[k]*y[n]。 :1,$s/a\[i]\*b\[j]/x[k]*y[n]/g 将buf.length/1000替换为 buffer.size/1024。 :1,$s/buf\.length\/1000/buffer.size\/1024/g 在这里模式和替换字符串中的斜线前加转义符\,以区别于替换命令格式中所必须的斜线。 (4) 在编辑C语言程序的时候,将f[n]替换为f[i]。 使用下面的命令:






