在初识Shell时,我们介绍过,Shell是一种弱类型语言。但是,Shell也是有变量类型的,但它的变量类型和C/C++的变量类型有点不一样。当我们运行Shell时,会同时存在三种变量:
- 本地变量:局部变量在脚本或者命令中定义,仅在当前Shell实例中有效,其他Shell启动的程序不能访问局部变量。
- 环境变量:所有的程序,包括Shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候Shell脚本也可以定义环境变量。
- Shell变量:Shell变量是由Shell程序设置的特殊变量。Shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了Shell的正常运行。
先来举一个例子:
我们在父shell上定义了一个变量,直接在交互式父shell中,访问是可以直接访问的。但是,在子脚本中访问,却没有访问到。
使用export命令将myval变量导成环境变量,发现直接就可以显示出来了。
- 本地变量
只存在于当前Shell进程,用set命令可以显示当前Shell进程中定义的所有变量(包括本地变量和环境变量)和函数。上面的myval在没有被export时,就是父Shell内的一个本地变量。环境变量是任何进程都有的概念,而本地变量是Shell特有的概念。
- 环境变量
环境变量是可以从父进程传给子进程,因此Shell进程的环境变量,可以从当前Shell进程传给fork出来的子进程。用printenv命令可以显示当前Shell进程的环境变量。
一个变量定义后仅存在于当前Shell进程,它是本地变量,用export命令可以把本地变量导出为环境变量,定义和导出环境变量通常可以一步完成:
也可以分成两步完成:
用unset命令可以删除已定义的环境变量或本地变量。
- 拼接字符串
在上一篇博客中,我们已经学习了一种拼接字符串的方法。原则上,只要将信息写在一起,就可以完成对字符串的拼接,但是有一些特殊的地方,下面我们来一一学习一下:
在这里,我们需要注意的一点是:在Shell中,字符串可以用单引号,也可以用双引号,也可以不用引号。
- 获取字符串长度
- 提取子字符串
上面这个例子是从字符串的第1个字符开始截取7个字符,得到的结果就是impossible这个子字符串。
- 查找子字符串
需要特别注意的是:
- 文件名替换:* ? []
这些用于匹配的字符称为通配符,具体如下:
通配符* :匹配0个或多个任意字符;
? :匹配一个任意字符;
[若干字符]:匹配方括号中任意一个字符的一次出现
注意,通配符所匹配的文件名是由Shell展开的,也就是说,在参数还没有传给程序之前已经展开了。比如说,上述lsfile[1-5]命令,如果当前目录下有file1~file5,则传给ls命令的参数实际上是这5个文件名,而不是一个匹配字符串。总结起来就是:通配符匹配文件名时,先展开再传递。
- 命令代换和算数代换
Shell脚本中默认的执行方式是算数拼接。
由反引号``括起来的也是一条命令,Shell先执行该命令,然后将输出结果立即代换到当前命令行中。
命令代换也可以用$( )表示:
(( ))中的Shell变量取值将转化成整数,常用于算数计算,例如:
如果要对算数运算结果进行赋值或者作为右值,需要:
(( ))中只能用+ - * /和( ) 运算符,并且只能做整数运算。
- 转义字符
和C语言类似,\ 在Shell中被用作转义字符,用于去除紧跟其后的单个字符的特殊意义(回车除外)。换句话说,紧跟其后的字符取字面值。另外,\ 还可以紧跟其后的普通字符取特殊含义。
比如创建和删除一个文件名为$ $(中间有空格)的文件,就可以这样操作:
另外,还有一个字符虽然不具有特殊含义,但是要用它做文件名也很麻烦,那就是 - 号(减号)。如果要创建一个文件名以 - 号开头的文件,这样是不行的。即使加上 \ 转义也还是会报错,因为各种UNIX命令都把 - 号开头的命令行参数当做命令的选项,而不会当作文件名。如果非要处理以 - 号开头的文件名,可以有两种方法:
\ 还有一种用法,在 \ 后敲回车表示续行,Shell并不会立即执行命令,而是把光标移到下一行,给出一个续行提示符 > ,等待用户继续输入,最后把所有的续行接到一起当做一个命令执行。例如:
- 单引号和双引号
和C语言不一样,Shell脚本中的单引号和双引号一样都是字符串的界定符,而不是字符的界定符。单引号用于保持引号内所有字符的字面值,即使引号内的 \ 和回车也不例外,但是字符串内不能出现单引号。如果引号没有配对就输入回车,Shell会给出续行提示符,要求用户把引号配上对。
要搞清楚Shell单引号和双引号的区别,我们可以看看下面这个典型的例子:
双引号用于保持引号内所有字符的字面值(回车也不例外),但以下情况除外:
(1)$ 加变量名可以取变量的值
(2)反引号仍表示命令替换
(3)$ 表示 $ 的字面值
(4)` (反引号)表示 ` 的字面值
(5)" 表示 " 的字面值
(6) \ 表示 \ 的字面值
除以上情况之外,在其它字符前面的 \ 无特殊含义,只表示字面值。