Shell 简介
shell本身是一个用C语言编写的程序,用户通过它来使用Linux ,用户的大部分工作都是通过Shell来完成的。
shell既是一种命令语言,也是一种程序设计语言。作为命令语言,它交互式的解释和执行用户输入的命令;而作为程序设计语言,提供了一些高级程序
设计语言才有的控制结构,包括循环和分支。
shell执行命令的方式有两种:
交互式(Interactive): 解释执行用户的命令,用户输入一条执行一条。
批处理(Batch) : 用户实现写一个shell脚本(script),其中包含多条命令,然后shell一次性全部执行。
几种常见的Shell
linux上常见的shell脚本解释器bash、sh、csh、ksh。
bash(BourneAgain Shell)from Brain Fox feat Chet Ramy.它是Linux标准的默认shell, 内部命令一共有40个。它有以下特点:
可以使用类似DOS下面的doskey的功能,用方向键查阅和快速输入并修改命令。
自动通过匹配的方式给出以某字符串开头的命令。
包含了自身的帮助功能,你只要在提示符下面键入help就可以得到相应的帮助。
sh(Bourne Shell)from Steve Bourne. 是Unix标准默认的shell。
ash form Kennith Almquist. 它是Linux中占用系统资源最少的 一个小shell,只包含24个内部命令,因而使用起来不方便。
csh form Wiliam Joy. 它是Linux比较大的内核,共有52个内部命令。该shell其实是指向/bin/tcsh的,所以csh就是tcsh
ash(Korn Shell)form Eric Gisin. 共有42个内部命令,最大的优点是几乎和商业发行版的ksh完全兼容。
Shell脚本语言与编译语言的区别
程序设计语言大致可以分为编译型语言和解释型语言。
编译型语言
此类语言需要预先将我们编写的源代码(source file) 转换成目标代码(object code) ,此过程即为“编译”。
优点:运行程序时直接读取目标代码,由于编译后的目标代码与底层计算机代码非常接近,所以执行效率很高。
缺点:因为编译型语言大多都在底层运行,所处理的都是字节、整数、浮点数或是其他机器层级对象,所以实现一个简单的
功能需要大量复杂的代码。(ep: c++内讲一个目录下所有文件复制到另一个目录中)
脚本型语言
即解释型语言。执行此类程序时,解释器需读取我们编写的源码,并将其转换成目标代码,再有计算机运行,由于每次执行
都有这个编译的过程,所以效率会有所下降。脚本语言的好处在于它们运行在比编译型语言高的层级,能够轻易处理文件与目录
之类的对象;缺点是效率一般不如编译型语言。脚本语言的例子有aw、Perl、Python、Ruby、Shell等。
什么时候该使用Shell
Shell是个Unix系统之间通用的而功能,且经过了POSIX的标准化。因此Shell脚本的重用性很高。
之所以要使用Shell脚本是基于:
简单性:Shell是一个高级语言;通过它可以间接地表达复杂的操作。
可移植性:使用POSIX所定义的功能,可以做到脚本无需修改就可以在不同的系统上执行。
开发容易:可以在段时间内完成一个功能强大又好用的脚本。
但考虑到Shell脚本的命令限制和效率问题,下列情况一般不使用Shell:
1,资源密集型的任务,尤其在需要考虑效率时(如排序、hash等等)。
2,需要处理大人物的数学操作,尤其是浮点运算,精确运算或者复杂的算术运算(此情况一般使用C++或FORTRAN来处理)。
3,有跨平台(操作系统)移植需求(一般使用C或Java)。
4,复杂的应用,在必须使用结构化变成的时候(需要变量的类型检查,函数原型,等等)。
5,对于影响系统全局性的关键任务应用。
6,对于安全有很高要求的任务,比如需要一个健壮的系统来防止入侵、破解、恶意破坏等等。
7,项目由连串的依赖的各个部分组成。
8,需要大规模的文件曹组。
9,需要多维数组的支持。
10,需要数据结构的支持,比如链表或树等。
11,需要产生或操作图形化界面GUI。
12,需要之间操作系统硬件。
13,需要I/O或socket接口。
14,需要使用库或者遗留下来的老代码的接口。
15,私人的、闭源的应用(shell脚本把代码就放在文本文件中,全世界都可以看到)。
如果应用符合以上任意一条,可以考虑更强大语言,如Perl、Tcl、Python、Ruby--或者更高层次的编译语言如C/C++,Java.
第一个简单Shell
打开文本编辑器,建立一个后缀名为.sh的测试文件,编辑文件内容并保存
#! /bin/bash (#! 表示使用哪一种shell来执行该脚本 )
echo "Hello world"
运行Shell脚本有两种方法,一是作为可执行程序,而是作为解释器参数
作为可执行程序
保存之后使用chmod命令为该文件添加执行权限,然后运行该脚本
chmod +x ./test.sh
./test.sh
如果不先给该脚本添加执行权限直接执行会抛出拒绝执行的错误
作为解释器参数
此方式直接运行解释器,然后参数就是该脚本文件名(不添加执行权限也可执行)
/bin/bash test.sh

第二个实例,使用read命令,从键盘获取输入赋值值某个变量然后取出
先创建文件another.sh,然后编辑内容添加执行权限,再执行脚本


Shell变量
Shell定义变量不需类型符,直接输入变量名等于号即可
注意点:变量名和等号之间不能有空格
变量名命名规则:
- 首字符必须为字符(a-z,A-Z).
- 中间不能有空格,可使用下划线(_).
- 不能使用标点符号,不能使用bash里的关键字.
使用一个已定义的变量只需在变量前加个美元符($)即可({}是为使变量的 边界更明显)

变量可以被重新赋值
readonly命令可以将变量定义为只读变量,其值之后将不可改变
unset命令可以删除变量,被删除的变量不能再次使用;该命令不可删除只读变量。

Shell特殊变量
特殊变量——某些有特殊意义的包含其它字符的变量。

$@与$*的区别
二者都是表示传递给函数或脚本的所有参数,不被双引号("")包含时,都已"$1""$2"..."n"形式输出所有参数
当二者都被双引号包含时,$@依旧是将每个参数分隔开以"$1""$2"..."n"形式输出所有参数,但是$*会将所有参数当一个整体以"$1$2...n"形式输出
$?表示获取上一条命令的退出状态,退出状态是一个数字,成功返回0,失败返回1;另外有一些命令返回其他值,表示不同错误
Shell替换
如果表达式中包含一些特殊字符,Shell将会进行替换。

命令替换
命令替换是指可以Shell可以先执行某些命令,然后将命令保存下来,在合适的地方再输出
语法:`command` 。注:``不是单引号,是反引导号,位于Esc键下方

示例如下:

Shell运算符
Bash支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。
原生Bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr(此命令为常用命令)。
算数运算符
expr是一款表达式计算工具,使用它能完成表达式的求值操作。

注意点:
表达式和运算符之间需要有空格,完整的表达式要被反引导号括起来{``,位于Esc键下方}
乘法运算符需使用转义字符("\")

关系运算符

布尔运算符

字符串运算符

文件测试运算符

Shell字符串
字符串是Shell里面常用数据类型,它可以使用单引号也可以使用双引号。
单引号字符串的限制:
单引号字符串里所有字符都原样输出,变量无效。
单引号字符串中不能出现单引号(使用转义字符之后一不行)
双引号:
双引号中可以有变量,也可以出现转义字符

Shell数组
Bash支持一维数组(不支持多维数组),并且不限定数组大小。下标从0开始编号,获取数组中的元素利用下标
下标可以是整数或者算数表达式,其值应大于0。
在shell中,用括号来表示数组, 数组元素用空格隔开,数组定义的一般形式为:
array_name=(value0 value1 value2 value3 ... value n)
或者
array_name=(
value0
value1
value2
...
valuen
)
还可以单独定义数组的各个分量:
array_name[0]=value0
array_name[1]=value1
可以不使用连续的下标,而且下标的范围没有限制
读取数组的格式一般是${array_name[index]}
使用@或*可以读取数组中的所有数据 格式为${array_name[@]}或${array_name[*]}

Shell printf命令
printf命令用于格式化输出,用法 printf format-string [arguments]
fromat-string是格式控制字符串,arguments是参数列表
该命令与C语言中printf()函数的区别:
printf命令不用加括号
format-string可以没引号
参数多余格式控制符时,format-string可以重用,将所有参数都转换
arguments使用空格分开,不使用逗号
如果没有arguments ,则%s输出null,%d输出0
Shell if else 语句
if else用来判断分支,shell中有三种if...else 语句:if...else ; if...else...fi ; if...elif...else...fi





if...else 语句也可以全部写到一行,语句末尾使用分号隔开。

Shell case...esac 语句
case...esac与其他语句中的switch...case语句想死,是一种多选择分支语句。


Shell 循环语句
For循环
for循环格式一般为:
for 变量 in 列表
do
command1
command2
....
commandn
done
列表是一组值组成的序列,以空格分隔开。

While循环
while command
do
something to do
done
命令执行至command为假,跳出循环

while语句可以从键盘读取输入值

Until循环
until刚好与while循环的处理方式相反,条件为真时循环结束
until command
do
something to do
done
命令执行至command为真,跳出循环
循环中断
Shell也是使用continue 和break命令来跳出循环。
Shell 函数
shell函数必须先定义后使用,格式如下:
function function_name(){ ps:函数名前面的关键字function可以省略
list commands
[ return value ]
}
如果不加return语句,则将最后一条命令的运行结果作为返回值。
Shell的函数返回值只能是一个整数,一般用来表示函数是否执行成功,0表示成功,其他值为失败。如果return其他数据,会报错
如果一定要返回一个字符串,则可使用一个变量用来接收函数的计算结果,脚本在需要的时候访问此变量。
函数返回值在调用函数之后使用$?来获取
函数也可以嵌套使用,删除函数使用unset命令, 格式为 : unset .f function_name

在调用函数的地方,可以函数传递参数,在函数体内部通过$n来获取参数值

Shell 输入输出重定向
一般命令默认的输入为键盘,输出为显示器,但是命令的输出不仅仅是显示器,也可以重定向至其他位置,如文件
输出重定向命令: command > file_name或command >> file_name
二者区别为>会覆盖文件内的内容,而>>是在文件后追加输出,不会覆盖原内容
输入重定向命令: command < file_name 此命令表示从文件内读取输入
