【Linux】shell基础之符号篇

我们以前可能也听过shell这个名词,但是并未深入了解,本片博客旨在揭开shell神秘的面纱。
一、与shell相关的一些概念的介绍
1、Shell定位、
(1)Shell是一种用c语言编写的程序,它是用户使用Linux的桥梁。Shell既是一种命令语言又是一种程序设计语言
(2)Shell是指一种应用程序,一种和内核沟通的外壳应用程序的统称。有时会提供一个界面,用户通过这个界面访问操作系统内核的服务
2、Shell和Bash
Bash就是一种常见的Shell,形象的来说,Shell叫做媒婆,Bash就是王婆,是一种包含关系
3、Shell脚本
(1)Shell脚本,是一种为shell编写的脚本程序
(2)通常所说的shell通常都是指shell脚本,但是,shell和shell script是两种不同的概念
(3)由于习惯的原因,我们认为“shell编程”都是指shell脚本编程
4、Shell开发环境
(1)Shell编程和java、php、python编程一样,只要有一个文本编辑器和一个解释器就可以了
(2)Linux的Shell解释器种类很多常见的有:Bource Shell(/usr/bin/sh或者/bin/sh)、Bource Again Shell(/usr/bin/bash)、C Shell(/usr/bin/csh)、K Shell(/usr/bin/ksh)、Shell for Root(/sbin/sh)
(3)我们关注的是Bash,也就是Bourne Again Shell,也就是大多数Linux系统默认的Shell
5、shell特点
(1)解释非编译型
(2)弱类型
(3)执行模式:交互式/批处理式
一个简单的Shell脚本
这里写图片描述
注意:(1)#!是一个约定的标记,用于告诉系统使用那一种解释器,即使用哪一种shell,通常(#!)叫做“Shebang”或者“Sha-bang”
(2)echo命令用于向窗口输出文本
执行shell脚本有两种方式:
(1)给shell脚本加一个可执行权限就可以直接用./加上脚本文件来执行
如果不加./直接写文件名字,linux系统会在PATH里寻找,我们写的程序一般都不在PATH里,所以就无法执行,而./就相当于告诉系统这个文件就在当前目录下
(2)前面加上解释器,把该shell文件作为解释器的参数来执行
这种执行方式,直接运行解释器,参数就是文件名,不需要在第一行指定解释器信息,写了也用不到
这里写图片描述
shell脚本中用#表示注释
但是如果#位于第一行开头例外,表示该脚本使用后面的解释器来解释
6、解释执行本质原理
(1)第一种执行方式,加可执行权限,shell会fork一个子进程并调用exec执行./first.sh这个程序,exec系统调用应该把子进程的代码段替换成./first.sh程序的代码段,并从它的_start开始执行
(2)然而first.sh是个文本文件,根本没有代码段和_start函数,其实exec还有另外一种机制,如果要执行的是一个文本文件,并且第一行用Shebang指定了解释器,则用解释器程序的代码段替换当前进程,并且从解释器的_start开始执行,而这个文本文件被当做命令行参数传给解释器
(3)交互Shell(bash)fork/exec一个子Shell用于执行脚本,父进程bash等待子进程终止
(4)sh读取脚本中的cd ..命令,调用相应的函数执行内建命令改变当前工作目录为上一级目录
(5)sh读取脚本中的ls命令,fork/exec这个程序,列出当前目录下的文件sh等待ls终止
(6)ls终止后,sh继续执行,读到脚本文件末尾,sh终止
(7)sh终止后,bash继续执行,打印提示符等待用户输入
这里写图片描述
由图中发现虽然打印出来的目录变了,可是直接在命令行输入pwd发现目录并没有改变,这个解释就是这里用创建子进程来解释脚本
这里写图片描述
可是直接在命令行上执行上面的命令发现目录改变了,两个过程都是用同样的命令,为什么结果不同呢?说好的创建子进程呢?实际上,执行命令并不是一定要创建子进程,这些不需要创建子进程的命令叫做shell的内置命令,由父bash亲自执行,可以将该类命令理解成shell的内部函数即可。
这里写图片描述
这里写图片描述
我们发现,用. 或者source修饰脚本,脚本的执行影响到了父bash,这种方式不会创建子Shell
二、Shell变量
shelll是弱类型语言,原则上不需要强调shell变量,或者shell可以放很多常见内容,shell变量也不需要提前定义,或者不牵扯到定义一说,需要时直接使用即可
1、赋值命名规则
注意变量和等号之间不能有空格否则会被解释成命令,变量名的命名必须遵循如下规则:
(1)首个字符必须为字母(a-z,A-Z)
(2)中间不能有空格,可以使用下划线
(3)不能使用标点符号
(4)不能使用bash里面的关键字(可以help查看)
2、shell变量可以放入你想放入的很多内容
这里写图片描述
3、使用变量
想要使用一个赋值过的变量,只要在变量前面加$符号即可
这里写图片描述
可以看出我们想输出得是hello worldhello bit,实际上只输出了部分,原因是shell将mystring和hello认为成了一个新的变量名,而这个变量名没有被赋值所以位空串
这里写图片描述
当我们加上一个大括号之后结果就能正确输出了,加大括号的作用是帮助解释器识别变量的边界,所以应该养成给每一个变量加上大括号的习惯

已定义的变量,可以被重新定义
但是第二次赋值时,变量名前面不能加“$”,加上$只能做右值
4、只读变量
使用readonly命令可以将变量定义为只读变量,只读变量的值不能被改变
这里写图片描述
5、删除变量
使用unset命令可以删除变量
这里写图片描述
unset不能删除只读变量
这里写图片描述
6、变量类型
我们前面提到了shell脚本是弱类型,也有变量类型吗,shell的变量类型和c/c++变量类型有点不一样
(1)本地变量:局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量
(2)环境变量:所有的程序,包括shell启动的程序都能访问环境变量,有些程序需要环境变量来保证其正常运行,必要的时候shell脚本也可以定义环境变量
(3)shell变量:shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
这里写图片描述
我们在父shell上定义了一个变量,直接交互式父shell中,访问是可以直接访问的,但是在子脚本中访问,却访问不到
这里写图片描述
将myval变量导成环境变量子shell就可以访问到了
7、拼接字符串
原则上只要将信息写在一起,就完成了string的拼接,当然有一些特殊的地方
这里写图片描述
(1)获取字符串长度
这里写图片描述
(2)提取字符串
这里写图片描述
(3)查找字符串
这里写图片描述
三、文件名代换::*?[]
这些用于匹配的字符称为通配符
(1)通配符*:匹配0个或多个任意字符
(2)?:匹配任意一个字符的一次出现
(3)[若干字符]:匹配方括号中任意一个字符的一次出现
这里写图片描述
注意:Globbing所匹配的文件名是由Shell展开的,也就是说在参数还没传给程序之前已经展开了,比如上面ls file[1-5]命令,如果当前目录下有file1-file5,则传给ls命令的参数实际上是这5个文件名,而不是一个匹配字符串
四、命令代换和算术代换
由反引号“括起来的也是一条命令,Shell先执行该命令然后将输出结果立刻代换到当前命令行中
这里写图片描述
命令代换也可以用$()表示:DATE=$(date +%Y:%m:%d)
(())中的shell变量取值将转换成整数,常用于算术计算,例如:
这里写图片描述
如果要对运算结果进行赋值或者作为右值
这里写图片描述
(())中只能用+-*/和()运算符,并且只能做整数运算
五、转义字符
和c语言类似,\在Shell中被用作转义字符,用于去除紧跟在后面的单个字符的特殊意义(回车除外),换句话说,紧跟在其后的字符字面值。另外,\还可以紧跟其后面字符取特殊含义
这里写图片描述
另外还有一个字符虽然不具有特殊含义,但是要用它做文件名也很麻烦,就是.号。如果创建一个文件名以.号开头的文件,这样是不行的:即使加上\转义还是报错,因为各种unix命令都把.号开头的命令行参数作为命令的选项而不会当做文件名,,如果非要处理以.开头的文件名可以有两种办法
这里写图片描述
\还有一种用法,在\后敲回车换行表示续行,Shell并不会立刻执行命令,而是把光标移到下一行,给出一个续航提示符>等待用户继续输入,最后把所有的续行接在一起当做一个命令执行
这里写图片描述
六、单引号双引号
和c语言不一样,Shell脚本中的单引号和双引号一样都是字符串的界定符。单引号用于保持引号内所有字符的字面值,即使引号内的\和回车也不例外,但是字符串中不能出现单引号。如果引号没有配对就输入回车,Shell会给出续行提示符,要求用户把引号配上对
这里写图片描述
(1)$加变量名可以去变量的值
(2)反引号仍表示命令替换
(3)$表示$的字面值
(4)反引号表示的字面值
(5)\”表示”的字面值
(6)\表示\的字面值除以上情况之外,在其它字符前面的\无特殊含义,只表示字面值

猜你喜欢

转载自blog.csdn.net/flowing_wind/article/details/81082049
今日推荐