http://www.tsnc.edu.cn/default/tsnc_wgrj/doc/abs-3.9.1_cn/html/index.html
高级Bash脚本编程指南
一本深入学习shell脚本艺术的书籍
Mendel Cooper
春敏 杨 -
毅 黄 -
3.9.12006年5月26日
这本书假定你没有任何关于脚本或一般程序的编程知识, 但是如果你具备相关的知识, 那么你将很容易就能够达到中高级的水平. . . 所有这些只是UNIX®浩瀚知识的一小部分. 你可以把本书作为教材, 自学手册, 或者是关于shell脚本技术的文档. 书中的练习和样例脚本中的注释将会与读者进行更好的互动, 但是最关键的前提是: 想真正学习脚本编程的唯一途径就是亲自动手编写脚本.
这本书也可作为教材来讲解一般的编程概念.
本文档的最新版本是作为一个归档文件bzip2-ed, "tar包"来发布的, 其中还包括SGML源代码和编译好的HTML版本. 读者可以从作者的主页上下载. pdf版本也可以从作者的主页上下载. 查看change log来查看校订历史.
贡献
献给Anita, 我所有动力的源泉!
-
目录
序
-
-
1.
原书作者致中国读者(英文)
2.
原书作者致中国读者(译文)
3.
黄毅
4.
杨春敏
第一部分.
热身
- 第二部分. 基本
- 第三部分. 进阶
-
-
9.
变量重游
-
-
9.1.
内部变量
9.2.
操作字符串
9.3.
参数替换
9.4.
指定变量的类型: 使用declare或者typeset
9.5.
变量的间接引用
9.6.
$RANDOM: 产生随机整数
9.7.
双圆括号结构
10.
循环与分支
-
-
10.1.
循环
10.2.
嵌套循环
10.3.
循环控制
10.4.
测试与分支(case与select结构)
11.
内部命令与内建命令
-
-
11.1.
作业控制命令
12.
外部过滤器, 程序和命令
- 13. 系统与管理命令
-
-
13.1.
分析一个系统脚本
14.
命令替换
15.
算术扩展
16.
I/O重定向
- 17. Here Document
-
-
17.1.
Here String
18.
休息片刻
第四部分.
高级主题
-
-
-
19.
正则表达式
-
-
19.1.
一份简要的正则表达式介绍
19.2.
通配(globbing)
20.
子shell
21.
受限shell
22.
进程替换
23.
函数
-
-
23.1.
复杂函数和函数复杂性
23.2.
局部变量
23.3.
不使用局部变量的递归
24.
别名
25.
列表结构
26.
数组
27.
/dev和/proc
- 28. Zero与Null 29. 调试 30. 选项 31. 陷阱 32. 脚本编程风格
-
-
32.1.
非官方的Shell脚本编写风格
33.
杂项
-
-
33.1.
交互与非交互式的交互与非交互式的shell和脚本
33.2.
Shell包装
33.3.
测试和比较: 一种可选的方法
33.4.
递归
33.5.
将脚本"彩色化"
33.6.
优化
33.7.
各种小技巧
33.8.
安全问题
33.9.
可移植性问题
33.10.
Windows下的shell脚本
34.
Bash, 版本2与版本3
35.
后记
-
- 参考文献 A. 捐献的脚本 B. 参考卡片 C. 一个学习Sed和Awk的小手册
- D. 带有特殊含义的退出码 E. I/O和I/O重定向的详细介绍 F. 命令行选项
- G. 重要的文件 H. 重要的系统目录 I. 本地化 J. 历史命令 K. 一个简单的.bashrc文件 L. 将DOS批处理文件转换为Shell脚本 M. 练习
- N. 修订记录 O. 翻译版修订记录 P. 镜像站点 Q. To Do列表 R. 版权
-
表格清单
11-1.
作业标识符
30-1.
Bash选项
33-1.
转义序列中颜色与数值的对应
B-1.
特殊的shell变量
B-2.
测试操作: 二元比较
B-3.
文件类型的测试操作
B-4.
参数替换和扩展
B-5.
字符串操作
B-6.
一些结构的汇总
C-1.
基本sed操作
C-2.
sed操作符举例
D-1.
"保留的"退出码
L-1.
批处理文件关键字 / 变量 / 操作符, 和等价的shell符号
L-2.
DOS命令与UNIX的等价命令
N-1.
修订历史
O-1.
翻译版修订历史
-
例子清单
2-1.
清除: 清除/var/log下的log文件
2-2.
清除:一个改良的清除脚本
2-3.
清除: 一个增强的和广义的删除logfile的脚本
3-1.
代码块和I/O重定向
3-2.
将一个代码块的结果保存到文件
3-3.
在后台运行一个循环
3-4.
备份最后一天所有修改的文件
4-1.
变量赋值和替换
4-2.
简单的变量赋值
4-3.
简单和复杂, 两种类型的变量赋值
4-4.
整型还是字符串?
4-5.
位置参数
4-6.
wh,
whois节点名字查询
4-7.
使用shift命令
5-1.
echo出一些诡异变量
5-2.
转义符
6-1.
退出/退出状态码
6-2.
反转一个条件的用法!
7-1.
什么是真?
7-2.
test, /usr/bin/test, [ ], 和/usr/bin/[都是等价命令
7-3.
算术测试需要使用(( ))
7-4.
测试那些断掉的链接文件
7-5.
算术比较与字符串比较
7-6.
检查字符串是否为null
7-7.
zmore
8-1.
最大公约数
8-2.
使用算术操作符
8-3.
使用&&和||进行混合条件测试
8-4.
数字常量表示法
9-1.
$IFS与空白字符
9-2.
定时输入
9-3.
再来一个, 定时输入
9-4.
定时read
9-5.
我是root么?
9-6.
arglist: 通过$*和$@列出所有的参数
9-7.
$*
和$@
的不一致的行为
9-8.
当$IFS
为空时的$*
和$@
9-9.
下划线变量
9-10.
在一个文本文件的段落之间插入空行
9-11.
转换图片文件格式, 同时更改文件名
9-12.
将音频流文件转换为ogg各式的文件
9-13.
模拟getopt
9-14.
提取字符串的另一种方法
9-15.
使用参数替换和错误消息
9-16.
参数替换和"usage"消息(译者注: 通常就是帮助信息)
9-17.
变量长度
9-18.
参数替换中的模式匹配
9-19.
修改文件扩展名:
9-20.
使用模式匹配来解析任意字符串
9-21.
对字符串的前缀和后缀使用匹配模式
9-22.
使用declare来指定变量的类型
9-23.
间接引用
9-24.
传递一个间接引用给awk
9-25.
产生随机整数
9-26.
从一幅扑克牌中取出一张随机的牌
9-27.
两个指定值之间的随机数
9-28.
用随机数来摇单个骰子
9-29.
重新分配随机数种子
9-30.
使用
awk来产生伪随机数
9-31.
C语言风格的变量操作
10-1.
一个简单的for循环
10-2.
每个[list]元素中都带有两个参数的for循环
10-3.
文件信息: 对包含在变量中的文件列表进行操作
10-4.
在for循环中操作文件
10-5.
在for循环中省略in [list]部分
10-6.
使用命令替换来产生for循环的[list]
10-7.
对于二进制文件的
grep替换
10-8.
列出系统上的所有用户
10-9.
在目录的所有文件中查找源字串
10-10.
列出目录中所有的
符号链接
10-11.
将目录中所有符号链接文件的名字保存到一个文件中
10-12.
一个C风格的for循环
10-13.
在batch mode中使用efax
10-14.
简单的while循环
10-15.
另一个while循环
10-16.
多条件的while循环
10-17.
C风格的while循环
10-18.
until循环
10-19.
嵌套循环
10-20.
break和continue命令在循环中的效果
10-21.
多层循环的退出
10-22.
多层循环的continue
10-23.
在实际的任务中使用"continue N"
10-24.
使用case
10-25.
使用case来创建菜单
10-26.
使用命令替换来产生case变量
10-27.
简单的字符串匹配
10-28.
检查输入字符是否为字母
10-29.
使用select来创建菜单
10-30.
使用函数中的select结构来创建菜单
11-1.
一个fork出多个自身实例的脚本
11-2.
使用printf的例子
11-3.
使用read来进行变量分配
11-4.
当使用一个不带变量参数的read命令时, 将会发生什么?
11-5.
read命令的多行输入
11-6.
检测方向键
11-7.
通过
文件重定向来使用
read命令
11-8.
管道输出到read中的问题
11-9.
修改当前工作目录
11-10.
使用"let"命令来做算术运算.
11-11.
展示eval命令的效果
11-12.
强制登出(log-off)
11-13.
另一个"rot13"版本
11-14.
在Perl脚本中使用eval命令来强制变量替换
11-15.
使用set命令来改变脚本的位置参数
11-16.
反转位置参数
11-17.
重新分配位置参数
11-18.
"Unsett"一个变量
11-19.
使用export命令来将一个变量传递到一个内嵌
awk的脚本中
11-20.
使用getopts命令来来读取传递给脚本的选项/参数
11-21.
"includ"一个数据文件
11-22.
一个(没什么用的)source自身的脚本
11-23.
exec命令的效果
11-24.
一个exec自身的脚本
11-25.
在继续处理之前, 等待一个进程的结束
11-26.
一个结束自身的脚本程序
12-1.
使用ls命令来创建一个烧录CDR的内容列表
12-2.
到底是Hello还是Good-bye
12-3.
糟糕的文件名, 删除当前目录下文件名中包含一些糟糕字符(包括
空白的文件.
12-4.
通过文件的inode号来删除文件
12-5.
Logfile: 使用xargs来监控系统log
12-6.
把当前目录下的文件拷贝到另一个文件中
12-7.
通过名字kill进程
12-8.
使用xargs分析单词出现的频率
12-9.
使用expr
12-10.
使用date命令
12-11.
分析单词出现的频率
12-12.
哪个文件是脚本?
12-13.
产生10-进制随机数
12-14.
使用tail命令来监控系统log
12-15.
在脚本中模拟"grep"的行为
12-16.
在1913年的韦氏词典中查找定义
12-17.
检查列表中单词的正确性
12-18.
转换大写: 把一个文件的内容全部转换为大写.
12-19.
转换小写: 将当前目录下的所有文全部转换为小写.
12-20.
Du: DOS到UNIX文本文件的转换.
12-21.
rot13: rot13, 弱智加密.
12-22.
产生"Crypto-Quote"游戏(译者: 一种文字游戏)
12-23.
格式化文件列表.
12-24.
使用column来格式化目录列表
12-25.
nl: 一个自己计算行号的脚本.
12-26.
manview: 查看格式化的man页
12-27.
使用cpio来拷贝一个目录树
12-28.
解包一个rpm归档文件
12-29.
从C文件中去掉注释
12-30.
浏览/usr/X11R6/bin
12-31.
一个"改进过"的strings命令
12-32.
在一个脚本中使用cmp命令来比较两个文件.
12-33.
basename和dirname
12-34.
检查文件完整性
12-35.
Uudecode编码后的文件
12-36.
查找滥用的链接来报告垃圾邮件发送者
12-37.
分析一个垃圾邮件域
12-38.
获得一份股票报价
12-39.
更新FC4(Fedora 4)
12-40.
使用ssh
12-41.
一个mail自身的脚本
12-42.
按月偿还贷款
12-43.
数制转换
12-44.
使用"here document"来调用bc
12-45.
计算圆周率
12-46.
将10进制数字转换为16进制数字
12-47.
因子分解
12-48.
计算直角三角形的斜边
12-49.
使用seq命令来产生循环参数
12-50.
字母统计
12-51.
使用getopt来分析命令行选项
12-52.
一个拷贝自身的脚本
12-53.
练习dd
12-54.
记录按键
12-55.
安全的删除一个文件
12-56.
文件名产生器
12-57.
将长度单位-米, 转化为英里
12-58.
使用m4
13-1.
设置一个新密码
13-2.
设置一个擦除字符
13-3.
保密密码: 关闭终端对于密码的echo
13-4.
按键检测
13-5.
扫描远程机器上的identd服务进程
13-6.
使用pidof命令帮忙kill一个进程
13-7.
检查一个CD镜像
13-8.
在一个文件中创建文件系统
13-9.
添加一个新的硬盘驱动器
13-10.
用umask将输出文件隐藏起来
13-11.
killall, 来自于/etc/rc.d/init.d
14-1.
愚蠢的脚本策略
14-2.
将一个循环输出的内容设置到变量中
14-3.
找anagram(回文构词法, 可以将一个有意义的单词, 变换为1个或多个有意义的单词, 但是还是原来的子母集合)
16-1.
使用exec重定向stdin
16-2.
使用exec来重定向stdout
16-3.
使用exec在同一个脚本中重定向stdin和stdout
16-4.
避免子shell
16-5.
while循环的重定向
16-6.
重定向while循环的另一种形式
16-7.
重定向until循环
16-8.
重定向for循环
16-9.
重定向for循环(stdin和stdout都进行重定向)
16-10.
重定向if/then测试结构
16-11.
用于上面例子的"names.data"数据文件
16-12.
事件纪录
17-1.
广播: 将消息发送给每个登陆的用户
17-2.
虚拟文件: 创建一个2行的虚拟文件
17-3.
使用cat的多行消息
17-4.
带有抑制tab功能的多行消息
17-5.
使用参数替换的here document
17-6.
上传一个文件对到"Sunsite"的incoming目录
17-7.
关闭参数替换
17-8.
生成另外一个脚本的脚本
17-9.
Here document与函数
17-10.
"匿名"的here Document
17-11.
注释掉一段代码块
17-12.
一个自文档化(self-documenting)的脚本
17-13.
在一个文件的开头添加文本
17-14.
分析一个邮箱
20-1.
子shell中的变量作用域
20-2.
列出用户的配置文件
20-3.
在子shell中进行并行处理
21-1.
在受限模式下运行脚本
23-1.
简单函数
23-2.
带参数的函数
23-3.
函数与传递给脚本的命令行参数
23-4.
将一个间接引用传递给函数
23-5.
对一个传递给函数的参数进行解除引用的操作
23-6.
再来一次, 对一个传递给函数的参数进行解除引用的操作
23-7.
取两个数中的最大值
23-8.
将阿拉伯数字转化为罗马数字
23-9.
测试函数最大的返回值
23-10.
比较两个大整数
23-11.
从username中取得用户的真名
23-12.
局部变量的可见范围
23-13.
使用局部变量的递归
23-14.
汉诺塔
24-1.
用在脚本中的别名
24-2.
unalias: 设置与删除别名
25-1.
使用"与列表"来测试命令行参数
25-2.
使用"与列表"来测试命令行参数的另一个例子
25-3.
将"或列表"和"与列表"结合使用
26-1.
简单的数组使用
26-2.
格式化一首诗
26-3.
多种数组操作
26-4.
用于数组的字符串操作
26-5.
将脚本的内容赋值给数组
26-6.
一些数组专用的小道具
26-7.
空数组与包含空元素的数组
26-8.
初始化数组
26-9.
拷贝和连接数组
26-10.
关于串联数组的更多信息
26-11.
一位老朋友: 冒泡排序
26-12.
嵌套数组与间接引用
26-13.
复杂的数组应用: 埃拉托色尼素数筛子
26-14.
模拟一个下推堆栈
26-15.
复杂的数组应用: 探索一个神秘的数学序列
26-16.
模拟一个二维数组, 并使他倾斜
27-1.
利用/dev/tcp来检修故障
27-2.
找出与给定PID相关联的进程
27-3.
网络连接状态
28-1.
隐藏令人厌恶的cookie
28-2.
使用/dev/zero来建立一个交换文件
28-3.
创建一个ramdisk
29-1.
一个错误脚本
29-2.
缺少
关键字
29-3.
test24, 另一个错误脚本
29-4.
使用"assert"来测试条件
29-5.
捕获exit
29-6.
Control-C之后, 清除垃圾
29-7.
跟踪一个变量
29-8.
运行多进程(在对称多处理器(SMP box)的机器上)
31-1.
数字比较与字符串比较并不相同
31-2.
子shell缺陷
31-3.
将echo的输出通过管道传递给read命令
33-1.
shell包装
33-2.
稍微复杂一些的shell包装
33-3.
一个通用的shell包装, 用来写日志文件
33-4.
包装awd脚本的shell包装
33-5.
另一个包装awd脚本的shell包装
33-6.
将Perl嵌入到Bash脚本中
33-7.
将Bash和Perl脚本写到同一个文件中
33-8.
递归调用自身的(没用的)脚本
33-9.
递归调用自身的(有用的)脚本
33-10.
另一个递归调用自身的(有用的)脚本
33-11.
一个"彩色的"地址数据库
33-12.
画一个盒子
33-13.
显示彩色文本
33-14.
"赛马"游戏
33-15.
返回值小技巧
33-16.
返回多个值的技巧
33-17.
传递数组到函数, 从函数中返回数组
33-18.
anagram游戏
33-19.
从shell脚本中调用窗口部件
34-1.
字符串扩展
34-2.
间接变量引用 - 新方法
34-3.
使用间接变量引用的简单数据库应用
34-4.
使用数组和其他的小技巧来处理4人随机打牌
A-1.
mailformat: 格式化一个e-mail消息
A-2.
rn: 一个非常简单的文件重命名工具
A-3.
blank-rename: 重命名包含空白的文件名
A-4.
encryptedpw: 使用一个本地加密口令, 上传到一个ftp服务器.
A-5.
copy-cd: 拷贝一个数据CD
A-6.
Collatz序列
A-7.
days-between: 计算两个日期之间天数差
A-8.
构造一个"字典"
A-9.
Soundex转换
A-10.
"Game of Life"
A-11.
"Game of Life"的数据文件
A-12.
behead: 去掉信件与新消息的头
A-13.
ftpget: 通过ftp下载文件
A-14.
password: 产生随机的8个字符的密码
A-15.
fifo: 使用命名管道来做每日的备份
A-16.
使用模操作符来产生素数
A-17.
tree: 显示目录树
A-18.
string functions: C风格的字符串函数
A-19.
目录信息
A-20.
面向对象数据库
A-21.
hash函数库
A-22.
使用hash函数来给文本上色
A-23.
深入hash函数
A-24.
挂载USB keychain型的存储设备
A-25.
保存weblog
A-26.
保护字符串的字面含义
A-27.
不保护字符串的字面含义
A-28.
鉴定是否是垃圾邮件服务器
A-29.
垃圾邮件服务器猎手
A-30.
使得wget更易用
A-31.
一个"podcasting"(译者: 指的是在互联网上发布音视频文件, 并允许用户订阅并自动接收的方法)脚本
A-32.
基础回顾
A-33.
一个扩展的cd命令
C-1.
计算字符出现次数
K-1.
.bashrc文件样本
L-1.
VIEWDATA.BAT: DOS批处理文件
L-2.
viewdata.sh: 转换自VIEWDATA.BAT的shell脚本
Q-1.
打印服务器环境