代码改变世界

Shell脚本学习指南 [ 第一、二章 ] 背景知识、入门

2017-02-26 20:17  牛仔裤的夏天  阅读(432)  评论(0编辑  收藏  举报
摘要:第一章介绍unix系统的发展史及软件工具的设计原则。第二章介绍编译语言与脚本语言的区别以及两个相当简单但很实用的Shell脚本程序,涵盖范围包括了命令、选项、参数、Shell变量、echo与printf的输出、基本输入/输出重定向、命令查找、从脚本里访问参数以及执行跟踪等。

第一章 背景知识

概括:这一章介绍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 '\r' < dos_file.txt
  *以>改变标准输出
  program > file 可将program的标准输出修改为file:
  tr -d '\r' < 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 '\r' < 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  国际化与本地化

 当国际化作为设计软件的过程时,软件无须再修改或重新编译程序代码,就可以给特定的用户群使用。当本地化作为软件的过程时,目的是让特定的用户群得以使用软件。