Shell简介:
shell是用户操作计算机的工具,是用户与系统之间的界面。
当需要计算机为人们服务时,用户将自己的意图通知shell,只有当shell正确地理解了这些以人类语言描述的意图,并且用内部的语言通知操作系统后,用户的命令才能得以正确的执行。
Unix的三个层次
①核心层:操作系统常驻内存的部分,直接与计算机交互。
②shell层:该层有实用性程序集,包括解释程序,汇编工具等。使用户与操作系统的核心接口。
③用户实用层:包括实用程序及系统外其他工具等。
Shell执行过程
shell会fork一个子进程并调用exec执行./script.sh这个程序,exec系统调用应该把子进程的代码段替换成./script.sh程序的代码段,并从它的_start开始执行。然而script.sh是个文本文件,根本没有代码段和_start函数,其实exec还有另外一种机制,如果要执行的是一个文本文件,并且第一行指定了解释器,则用解释器程序的代码段替换当前进程,并且从解释器的_start开始执行,而这个文本文件被当做命令行参数传给解释器。因此,执行脚本相当于执行程序。
输入命令执行shell脚本后
1. 交互式进程(父进程)创建一个子进程用于执行脚本,父进程等待子进程终止。
2. 子进程程序替换bash解释器。
3. 读取shell脚本的命令,将其以参数传递的方式传递给bash解释器。
4. 子bash对shell脚本传入的参数进行读取,读一行识别到他是一个命令,则再创建一个子进程,子bash等待该新进程终止。
5. 新进程执行该命令,执行完后将结果交给子进程。
6. 子进程继续读取命令,创建新进程,新进程执行该命令,将结果返回给子进程,知道执行完最后一条命令。
7. 子进程终止,将结果返回给交互式父进程。
注意
像export、cd、env、set这些内置命令,在键入命令行后,交互式进程不会创建子进程,而是调用bash内部的函数执行这些命令,改变的是交互式进程。
如果在命令行下,将多个命令用括号括起来,并用分好分割开来执行,交互式进程依然会创建一个子shell执行括号中的命令:
如果不加括号则是另一种情况,cd… 命令会直接在交互式shell下执行;
. 或者source这两个命令是shell的内建命令,这种方式不会创建子shell,而是直接在交互式shell下逐行执行脚本中的命令。
例
script.sh
#!/bin/bash
ls
echo “###########”
cd …
ls
shell变量
环境变量:shell进程的环境变量可以从当前shell进程传给fork出来的子进程。
本地变量:只存在与当前shell进程。
利用printenv可以显示当前shell进程的环境变量;利用set命令可以显示当前shell进程中的定义的所有变量包括环境变量和本地变量和函数。
一个shell变量定义后仅存在于当前shell进程,是一个本地变量。用export命令可以把本地变量导出环境变量。用unset命令可以删除已定义的环境变量或本地变量。
荔汁:
//分步 先定义后导出
COUNT=5
export COUNT
//一步完成定义和导出环境变量
export COUNT=5
//删除已经定义的环境变量
unset COUNT
变量的引用
引用shell变量要用到$符号,加{}可以防止歧义。
荔汁:
COUNT=5
echo $COUNT
echo ${COUNT}911
通配符Globbling、命令代换、单引号、双引号
1.常见的通配符
*:匹配0个或多个任意字符
?:匹配一个任意字符
[若干字符]:匹配方括号中任意一个字符的一次出现
2.命令代换
反引号`` 或者$()
script.sh:
#!/bin/bash
DATA=date +%Y:%m:%d
LL=$(ls -l)
echo $DATE
echo $LL
shell会先执行反引号$()中的命令,将结果代换到当前命令中!
反引号和$()
反引号本身就对\进行了转义,保留了本身意思,如果我们想在反引号总起到\的特殊意义,我们必须使用2个\来进行表示。
反引号中: \ =
$()中:\ =
注意:反引号是老的用法,()是新的用法,最好掌握()的用法。
算数代换:$(())
荔汁
将(2-1)的结果赋给SUB,并显示本地变量SUB
SUB=$((2-1))
echo $SUB
3.单引号和双引号
shell脚本中的单引号和双引号一样都是字符串的界定符,单引号用于保持引号内所有字符的字面值,而双引号有些情况则特殊。如果字符串中有特殊字符需要处理时就用双引号。
荔汁
#!/bin/bash
echo ‘\’
echo “\”
echo ‘date
’
echo “date
”