第一章 背景知识
概括:这一章介绍unix系统的发展史及软件工具的设计原则。
1.1 unix系统发展史
unix最初是由贝尔电话实验室的计算机科学研究中心开发的。第一版诞生于1970年。
1.2 软件工具设计原则
♦ 一次做好一件事
♦ 处理文本行,不要处理二进制数据
♦ 使用正则表达式
♦ 默认使用标准输入/输出
♦ 避免喋喋不休
♦ 输出格式必须与可接受的输入格式一致
♦ 让工具去做困难的部分
♦ 构建特定工具前,先想想
第二章 入门
概括:该章从编译语言与脚本语言间的取舍开始讨论,再介绍两个相当简单但很实用的Shell脚本程序,涵盖范围包括了命令、选项、参数、Shell变量、echo与printf的输出、基本输入/输出重定向、命令查找、从脚本里访问参数以及执行跟踪。最后则以国际化与本地化结束。
2.1 脚本编程语言与编译型语言的差异
编译型语言的好处是高效,缺点是多半运作于底层,脚本编程语言通常是解释型的,由解释器读入代码并转换成内部的形式,解释器本身是一般的编译型程序。
2.2 为什么要使用Shell脚本?
简单性:Shell是一个高级语言,通过它可以简洁地表达复杂的操作。
可移植性:使用POSIX所定义的功能,可以做到脚本无须修改就可以在不同的系统上执行。
开发容易:可以在短时间内完成一个功能强大又好用的脚本。
2.3 一个简单的脚本
查看系统有多少人登录:
$ cat > nusers #建立文件,使用cat复制终端的输入 who | wc -l #程序的内容 ^D #Ctrl-D表示end-of-file $chmod +x nusers #让文件拥有执行的权限 $./nusers #执行测试 2 #输出结果
2.4 自给自足的脚本:位于第一行的#!
当Shell执行一个程序时,会要求UNIX内核启动一个新的进程(process),以便在该进程里执行所指定的程序。内核知道如何为编译型程序做这件事,我们的nusers Shell脚本并非编译型程序;当Shell要求内核执行它时,内核将无法做这件事,并回应“not executable format file”(不是可执行的格式文件)错误信息。Shell收到此错误信息时,就会说“啊哈,这不是编译型程序,那么一定是Shell脚本”,接着会启动一个新的/bin/sh(标准Shell)副本来执行该程序。
当一个文件的开头的两个字符是#!时,内核会扫描该行其余部分,看是否存在可用来执行程序的解释器的完整路径。
2.5 Shell的基本元素
(1)命令与参数
分号可用来分隔同一行里的多条命令。
(2)变量
$ myvar=this_is_a_long_string_that_does_not_mean_much #分配变量值 $ echo $myvar #打印变量值
(3)简单的echo输出
语法: echo [string ...]
用途: 产生Shell脚本的输出
(4)华丽的printf输出
语法: printf format-string [arguments...]
说明: 第一部分是一个字符串,用来描述输出的排列方式,最好为此字符串加上引号。第二部分是与格式声明相对应的参数列表。
(5)基本的I/O重定向
在登录系统时,UNIX便将默认的标准输入、输出及错误输出安排成你的终端。I/O重定向就是你通过与终端交互,或者是在Shell脚本里设置,重新安排从哪里输入或输出到哪里。
①重定向与管道
Shell提供了数种语法标记,可用来改变默认I/O的来源端与目的端。由浅入深如下:
*以<改变标准输入
program < file 可将program的标准输入修改为file:
tr -d '
' < dos_file.txt
*以>改变标准输出
program > file 可将program的标准输出修改为file:
tr -d '
' < dos_file.txt > UNIX-file.txt
这条命令会先以tr将将dos-file.txt里的ASCII carriage-return(回车)删除,再将转换完成的数据输出到UNIX-file.txt。dos-file.txt里的原始数据不会有变化。
*以>>附加到文件
program >> file 可将program的标准输出附加到file的结尾处
*以|建立管道
program1|program2 可将program1的标准输出修改为program2的标准输入
虽然<与>可将输入与输出连接到文件,不过管道(pipeline)可以把两个以上执行中的程序衔接在一起。
tr -d '
' < dos-file.txt |sort > UNIX-file.txt
这条管道会先删除文件内的回车字符,在完成数据的排序之后,将结果输出到目的文件。
②特殊文件:/dev/null与/dev/tty
UNIX系统提供了两个对Shell编程特别有用的特殊文件。第一个文件/dev/null,就是大家所熟知的位桶(bit bucket)。传送到此文件的数据都会被系统丢掉。另一个特殊文件为/dev/tty。当程序打开此文件时,UNIX会自动将它重定向到一个终端[一个实体的控制台(console)或串行端口(serial port)],也可能是一个通过网络与窗口登录的伪终端]再与程序结合。这在程序必须读取人工输入时(例如密码)特别有用。
printf "Enter new password:" #提示输入 stty -echo #关闭自动打印输入字符的功能 read pass < /dev/tty #读取密码 printf "Enter again:" #提示再输入一次 read pass2 < /dev/tty #再读取一次以确认 stty echo #别忘了打开自动打印输入字符的功能 ...
(6)基本的I/O重定向
Shell会沿着查找路径$PATH来寻找命令。$PATH是一个以冒号分隔的目录列表,可以在列表所指定的目录下找到所要执行的命令。如果你要编写自己的脚本,最好准备自己的bin目录来存放它们,并且让Shell能够自动找到他们,只要建立自己的bin目录,并将它加入$PATH中的列表即可。
2.6 访问Shell脚本的参数
所谓的位置参数指的也就是Shell脚本的命令行参数。当它超过9,就应该用大括号把数字框起来。
echo first arg is $1
echo tenth arg is ${10}
根据用户名查找用户是否登录:
$cat > finduser #建立新文件 #!/bin/sh #finduser #查看第一个参数所指定的用户是否登录 who | grep $1 ^D #以end-of-file结尾 $ chmod +x finduser #设置执行权限 $ ./finduser root #测试寻找root
2.7 简单的执行跟踪
在脚本里,用set -x命令将执行跟踪的功能打开,然后再用set +x命令关闭它。
2.8 国际化与本地化
当国际化作为设计软件的过程时,软件无须再修改或重新编译程序代码,就可以给特定的用户群使用。当本地化作为软件的过程时,目的是让特定的用户群得以使用软件。