看了<Unix的设计思想>,不由自主但愿从新学习我曾经忽视的linux的shell脚本编程。我并非随波逐流,也不是那种顽固的技术党,只是很纯粹的想了解这么技术,若是你有什么好的想法,也能够跟我交流,下面是个人微博地址:linux
http://weibo.com/1752090185/profile?rightmod=1&wvr=5&mod=personinfoshell
若是你有跟我同样的学习热情,不妨跟我一块学习下去。编程
先说变量的定义:数组
变量的定义很是的简单,就是变量名=变量值,中间不加空格。若是你加上空格,那么shell会认为这个是一个命令而不是一个语句。而你在引用变量的 时候能够经过$变量名的方式来引用。其实你也能够经过${变量名}和$((变量名))的方式来取出它的值。$符号后面将被默认解析成变量,这里我作了一个 假设,好比你有一个变量为a,另一个变量为ab,那么它取的是a的值仍是ab的值呢?bash
若是出现的是下列这种语句呢?网络
$abc数据结构
对,应该是没有这个变量的,它会去查找abc这个变量,而这个变量咱们压根就没有定义过.那么若是咱们必定要取得a这个变量呢?相信你跟我同样已经有了答案,那就是写成${a}bc的形式。学习
接下来咱们要说到一个很特别的变量叫作环境变量,环境变量咱们能够理解为系统预设的宏,或者常量。固然这么说可能不合理,由于环境变量是能够设置的。子进程能够定义本身的环境变量,父进程会将环境变量的参数传递给子进程。测试
环境变量的设置要经过export命令,经过不带参数的export命令能够打印出全部的环境变量.也许有人会问,我为何要用export命令 呢?我用=同样能够定义变量。其实是这样的,咱们本身定义的变量只在进程内有效,是不会传递给子进程的。那怎么测试这样东西呢?咱们知道在shell执 行的大部分命令都是开启一个进程,发生了进程的上下文切换,咱们能够在shell命令行里面再启动一个shell做为上一个shell的子进程。spa
在启动shell以前咱们先定义两个变量
param1="david_chen"
export param2="chen_david"
接下来咱们执行一下shell,我这里使用的是bash,我就执行一下bash
好了,接下来咱们打印一下这两个参数吧,咱们发现,param1没有东西,而param2是正常的。
在shell里面,每一变量的类型咱们均可以理解为是一个字符串数组,也就是说在shell里面是没有类型的,也就是所谓的弱类型语言。
咱们知道咱们学习语言的本质目的是为了运算,咱们先说一下数学运算.数学运算里面有三个经常使用的命令:
expr,let 和 bc.
expr,let用于整数运算,而bc用于浮点数运算。
以前咱们提到过{}(())这两个算子,是用来引用变量的,这里咱们引入了另一个算子[],这些算子里面的变量都是能够不加$的,而能用于算数运 算的是(())和[] 也就是说这两个基本上是等价的。而在使用这些操做符号的时候必定要注意变量和符号之间要有空格。浮点数咱们就不深究了,有须要我会再回头来看下资料的。
接下来咱们接着咱们的第二个主题,文件描述符。
其实文件描述符就是一个句柄,或者说是一个字长的整数。其中的三个整数是被系统占用的也就是0,1,2。它们分别对应着标准输入,标准输出和错误。重定向的目的就是将这些流的方向从新定向到你但愿的地方。你可能将它持久化,多是管道,也多是网络。
不论咱们是标准输出,仍是错误输出,咱们都会在屏幕上看到信息,所以咱们能够看出,实际上标准输出和错误输出实际上对应的是同一个定向终端文件。也就是屏幕。咱们能够经过数字来制定文件描述符的定向流。
好比说 2>syserr.log 那么也就是将2描述符也就是错误输出定向到syserr.log这个文件流中,而1>sysout.log也是同样的道理。若是你采用这种方法那么你的标准定向就会发生变化。
命令格式为:
cmd 2>syserr.log 1>sysout.log
若是你认为2中的数据没有你须要的,你能够定向到一个很特殊的文件 /dev/null中,全部被定向到这个文件中的流都会被丢弃。
接下来我将介绍一个很是重要的数据结构,数组。称它为数组可能并不恰当,能够称它为映射表,和其余的脚本语言很是相似,这里咱们所说的数组同样具备映射功能。
数组的定义能够经过 array=(1 2 3 4)这种方式来定义,通常的脚本都会支持空格和,两种分割符号,可是在shell里面只支持空格。这里咱们仍是能够引用C语言中的指针思想,其实在 shell脚本中的数组就是一个地址指针。咱们知道,在数组中,数组的指针对应着索引0的位置,我尝试了一下打印$array:
发现真的如我所愿打印出1 那么对于指针运算是否支持呢?在前面咱们知道对于算数运算的算子是[].我尝试了一下指针的运算$[ array + 1].如咱们所料的同样它打印出索引为1的指针指向数值。咱们能够类比的推断出来,其实shell中的数组也是一种指针,经过对指针的运算,实际上获得的 仍是个指针。与咱们的传统变量不一样,传统变量获得的是一个具体的值。那就更加奇怪了不是吗?
咱们在定义一个变量a=1的时候,经过运算$[a+1]获得的是2,若是a是一个数组,咱们获得的是一个指针指向值。这两种大相径庭的操做只说明一 点。shell是有类型的,咱们姑且能够认为有两种,一种是普通类型,一种是指针类型。不过貌似全部的语言大都是这种模式,只不过对于弱语言来讲是后期绑 定的类型。
好的咱们上面讲了咱们在取得数组值的时候能够采用$[a+n]的方法来得到,还有一种是经过${a[n]}的形式来得到索引为n的值.若是咱们要遍历整个数组呢?
${array[*]}
这种写法可让咱们遍历整个数组。对于数组长度的运算采用$[#array[*]],就跟咱们的字符串数组同样。你定义了一个字符串数组a="123"
${#a}就是获得这个字符串数组的长度。说完索引数组,咱们接着说关联数组
关联数组以前是须要调用declare -A testarray来申明关联数组类型的,我也不知道为什么,我但愿有了解的读者能给我个答案。能够加个人微博@ -非子墨- 来跟我私信。
而后配置你的关联属性.对于关联数组中的key,你不得不给出[]下标,否则可能会出现"为关联数组赋值时必须使用下标"这种错误。因此关联数组的格式为:
([key1]=value1 [key2]=value2)
若是打印keys的话只须要在数组前面加上!符号~估计在数组中除了value就是key吧~~