读书笔记第三篇 Unix/Linux系统编程 第十章 sh 编程
目录
sh概述
sh语言标准
sh命令
sh控制语句
I/O重定向和嵌入文档
sh函数
sh中的通配符
命令行分组
eval语句
调试sh脚本
0、程序设计语言有哪些必备的要素和技能
- 良好的设计能力,能在程序开始之前做出大致的构想,每个重要模块都能做到心里有数。
- 可以有将程序分块处理的能力,减小每一个模块的难度,有将所有模块有机结合在一起的能力。
- 有完善的数据结构,最好能将函数与数据声明放在程序开头。
- 良好的交互性,有输入提示,较低难度的数据输入要求。
- 其他
1、sh概述
- sh简介
sh即shell的缩写,sh是一种具备特殊功能的程序。与C语言不同,sh是一种解释语言而非编译性语言,它提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令,并把它送入内核去执行。Shell是一种应用程序,当用户登录Linux系统时,Shell就会被调入内存去执行。Shell独立于内核,它是连接内核和应用程序的桥梁,并由输入设备读取命令,再将其转为计算机可以理解的机械码,Linux内核才能执行该命令。
- sh脚本
sh脚本是一个包含了sh语句的文本文件,命令解释了程序sh要执行该语句。
- 演示一个可以输出"hello"的sh脚本:
1.先编辑一个包含以下内容的sh脚本文件
#! /bin/bash //#! 是一个约定的标记符号,指示脚本对应的解释器
# comment line
echo hello //此处为输出的内容
2.使用以下命令运行sh脚本
chmod +x mysh.sh //把mysh.sh文件转为可执行文件
./mysh.sh //运行脚本程序
- 运行结果如下:
- 还可以直接运行解释器,这样也可以运行脚本。代码如下:
/bin/sh mysh.sh //这种方法下就不需要第一行的解释器信息了
- sh与C
- 比较下列sh脚本和C程序
//sh 逐行读取并执行
mysh a b c d
$0 $1 $2 $3 $4
//C 编译链接至可执行文件 a.out
a.out a b c d
main(int argc , char *argv[])
-
sh是一种解释性语言,逐行读取sh脚本文件并直接执行这些行。如果是可执行的内置命令,那么就会直接执行,否则会复刻一个子进程来执行命令,并等待子进程终止后再继续,这和sh执行单个命令行一样。sh中的变量都是字符串。sh不需要main函数,sh脚本中的第一个可执行语句就是函数入口。
-
C程序要先编译链接到一个二进制可执行文件上,然后通过主sh的子进程运行这个可执行二进制可执行文件.在C程序中,每个变量都需要一个类型,如int、float、char等。C程序需要一个main函数作为函数的入口。
2、sh语言标准
- sh命令行参数
- 可以使用与运行sh命令完全相同的参数调用sh脚本,如:
mysh one two three //在实际操作中还是要按照下面的操作来
chmod +x file.sh
./file.sh
- 还可以通过位置参数$0、${11}等(09可直接用$n表示,10及以上用${}表示)来访问命令行参数。一般$0是程序名本身,$1$n是程序的的参数。在sh中,可以用内置变量$#和$*技术并显示命令行参数。
$# ---命令行参数$1~$n数目
$* ---所有命令行数,$#+1
$S ---执行sh的进程PID
$? ---最后一个命令执行的退出状态(成功时为0,否则为非0)
- 下列代码就是一个命令行参数应用的实例
vi mysh.sh
//
#! /bin/bash
echo \$# = $#
echo \$* = $*
echo $1 $9 $10
echo $1 $9 ${10}
shift //行位置顺序左移一位
echo $1 $9 ${10}
//
chmod +x mysh.sh
./mysh.sh abc D E F G H I J K L M N
- sh变量
sh有很多内置变量,如 PATH 、 HOME 、 TERM 等,除了这些内置变量外,还可以定义变量,定义的变量无需声明,sh的所有变量都是字符串,为赋值的sh变量是一个 NULL 字符串。
- sh变量的定义/赋值方法如下:
echo A //定义
A = 'askdjhlaksjdh' //赋值
- sh的引号
想要输出sh中的特殊字符,除了在前面加反斜杠以外,还可以用单引号" '' "来引用它们。
一般反斜杠"/"用于单个符号的引用,单引号" '' "用于长字符串。
单引号内没有替换,即单引号内的特殊符号会被视为字符,而双引号可以保留引用字符串中的空格和替换部分。
- sh语句
sh语句包含了Unix/Linux的所有命令。
3、sh命令
- sh的内置命令
sh有许多的内置命令,这些命令由sh执行,不需要创造一个新的进程
-
下面是一些常用的内置sh命令,如图下所见:
-
read命令,当sh执行read命令时,他会等待来自stdin(标准输入)的输入行。它将输入行划分为几个标记,分配给列出的变量。read的常见用法是允许用户与正在执行的sh进行交互,类似scanf()。
下面是一个read应用:
echo -n "enter your ID :"
read ANS
echo $ANS
- 结果如下:
- Linux命令
- echo命令
将参数符号对应的字符串作为行输出至stdout。一般会将多个相邻的空格合并为一个,除非有引号。echo已经用过很多次了。
- expr命令
将sh中的字符串转化为二进制数,经行运算后转回字符串。一般格式如下:
expr 字符串A 运算操作OP 字符串B
- 一个expr的使用例:
read A
read B
echo $(expr $A + $B)
- 结果如下:
- 管道命令
用来查找包含特定内容的文件
ps -ax | grep httpd
cat file | grep word
- 实用命令
- 命令替换
用括号括起来的部分会被优先处理
echo $(data)
echo $(ls dir) //先进行 ls dir 操作再输出整个 ls dir
4、sh控制语句
sh是一种编程语言,支持许多执行控制语句,类似C语言,注意格式的不同之处。
- if-else-if语句
if-else-if语句的一般格式:
if [中括号里的条件A]
then
分支A
else
分支B
fi //结束
或者是这种:
if [condition]; then
branchA
else
branchB
fi
又或者:
if [[ A && B]]; then
if [[ A && B || C]]; then
if [[ A && (B || C) ]]; then
- 注意,sh中的0代表TRUE,非0才代表FALSE。
- for语句
for语句的一般格式:
for A in Character
do
cmdA
done
- while语句
while语句的一般格式:
while [ 条件 ]
do
cmdA
done
- until-do语句
until-do语句的一般格式:
until [ $A = "never gone give you up" ]
do
cmdA
done
- case语句
case语句的一般格式:
case $A in
pattern1) cmd1;;
pattern2) cmd2;;
pattern3) cmd3;;
encase
- ps :
case在sh中用的不多
- continue 和 break
与C语言中一样
5、I/O重定向和嵌入文档
- 重定向输入输出
>file stdout转向文件,如果文件不存在,创建这个文件。
>>file stdout追加到文件中。
<file 将文件作为stdin;文件需要有r权限。
<<file 从"here"文件中获取输入,直到只包含"word"的行。
- 嵌入文档
指示输出命令从stdin获取输入,将其回显到stdout,直到遇到预先安排的关键字。
格式一般如下:
echo << END #一直按行输入并输出直到一行只剩下END
END
cat << DONE #一直按行输入输出直到DONE
DONE
6、sh函数
一般格式如下:
func()
{
# 函数内容
}
- 由于sh是按行执行的,所以必须先将所有的函数都定义好才能开始编写可执行语句。
7、sh中的通配符
- 星号通配符 * :可拓展到当前目录的所有文件
file *:列出当前目录中的所有文件信息
ls *.c:列出当前目录.c文件
- 问号通配符 ?:查询某文件的名字
file ???:所有有三个字符名字的文件
ls *.??:所有.后有两位拓展名的文件
- 中括号通配符 []:查询文件名中一对中括号中的字符
file *[ad]*:包含字符a或d的所有文件名
ls *[xyz]*:列出所有包含x、y或z的文件名
ls *[a-m]*:列出包括a到m范围内字符的所有文件名
8、命令分组
- 在sh脚本中,使用大括号{}或小括号()对命令进行分组,以达到组合使用命令的作用。
9、eval语句
- eval是一个sh的内置命令,即由sh自己执行,不需要新的进程。它将输入的参数字符串链接成一个字符串,每计算一次,就执行变量和命令的替换,然后给出结果字符串给sh使用。
格式如下:
eval [arg1 arg2 ...argn]
10、调试sh脚本
使用如下格式进行调试:
bash -x mysh