开始学shell挺有意思的,弱类型的语言再也没有写C的时候,那么多繁文缛节了,真特么爽,不过有爽的地方
就有扣脚的地方…
shell中的变量
首先,shell中的变量分为两类,局部变量和环境变量(全局变量)
局部变量
是每一个shell中可以使用的变量,在不同的shell中,是不能进行使用的
那么,如何界定一个shell呢?
bash shell是根据进程号进行界定的,对于每一个进程号,视为一个shell
环境变量
在学习Bash中提到过,环境变量,就是指在父shell以下的shell中都可以使用的变量
shell的环境变量是传下不传上,即向下的子shell,孙shell都可以继承该环境变量
而向上,父shell的父shell是不能使用的.
来举个实际的例子,Linux操作系统,登录时就是一个shell.
所以在他下面的所有子/孙shell的都可以继承环境变量
预设的环境变量
在shell中还预设了许多环境变量,这些变量可以直接使用,在shell脚本或者console交互界面
想让我给你详解吗,做梦,自己看去,
变量的操作
在shellscript中,变量的赋值,取值与C中还是有与很大的不同的
1. 定义变量
不需要进行类型的声明,弱类型,直接 “变量名=变量值”即可
注意,变量名与值之间仅仅相连,不允许有空格
当变量值中需要空格的时候,使用单/双引号括起来,不然会出现错误
[Crow@EvilCrow ~]$ var=5
[Crow@EvilCrow ~]$ echo $var
5
[Crow@EvilCrow ~]$ var = 6
bash: var: command not found
2. 变量取值
使用变量的值的时候,可以使用 “$变量名”,进行值的获取
严谨一点的写法: ${变量名}
看下面的例子:
[Crow@EvilCrow ~]$ var=Crow
[Crow@EvilCrow ~]$ echo Crow
Crow
[Crow@EvilCrow ~]$ echo $varhello --bash将varhello视为一个变量
[Crow@EvilCrow ~]$ echo ${var}hello --bash可以识别var为变量,并非是varhello
Crowhello
同时,如果需要引用其他变量,必须使用部分引用(弱引用)” “ 如果使用**强引用 ‘ ‘ **
则并不会进行变量的引用,会将一切视为普通字符
[Crow@EvilCrow ~]$ var=5
[Crow@EvilCrow ~]$ str="$var"
[Crow@EvilCrow ~]$ echo $str
5
[Crow@EvilCrow ~]$ str='$var'
[Crow@EvilCrow ~]$ echo $str
$var
3.取消变量
变量,可以设置,但是有的时候,我们就是想取消变量,那怎么办呢?
使用unset命令可以取消命令,也可以取消函数
declare var
var=5
func_1()
{
echo "In func_1"
}
echo "var = $var"
func_1
unset var
unset func_1
echo "After unset"
echo "var = $var"
func_1
4. 特殊变量
常用的特殊变量有以下两类:
位置变量: $0,$1,$2,$3,$#,$@,$* ,之前已经提过,不再赘述
脚本/命令的返回值: $? ,仅能表示上一个命令的返回值,成功为0,反之为非0
数组(Array)
数组,一直是个神奇的东西,很多语言都对其支持,而且合理使用数组,可以方便进行程序设计
在shellscript中数组,虽然没有其他地方强大,不过也差不到哪里去
首先,看看与其他语言数组的不同之处:
1> 区别于C/C++/Java这些编译型语言,sh为弱类型,所以,数组的元素是不会考虑类型的
2> 在大多数语言中,都是支持高维数组的,但是,sh中仅仅支持到一维数组
1.定义数组
定义数组很简单
declare -a array --即定义了一个数组
array[0]=0 --对数组中元素进行赋值
array[1]=1
数组使用起来还是比较像其他语言的,同时可以使用下标进行访问
同时,声明数组,也可以不使用declare关键字,不过就需要声明的同时进行初始化
declare -a name=("Crow" "Sue")
name=("Crow" "Sue")
sh中进行数组元素的增加是很简单的,声明数组后,进行赋值即可
未定义的下标,可以直接使用进行赋值
sh中数组用空格进行元素得分隔,不是使用逗号
declare -a array=(1 2)
array[2]=3
array[4]=6
echo ${array[*]}
2.数组操作
数组操作,在以往的语言中,都是基于函数,方法来进行操作的,毕竟OOP
但是,在sh中会带给你一种全新的方式进行数组的操作
1> 数组取值操作
数组进行取值时,直接使用下标,*进行索引取值即可,即 ** $ { 数组名 [ 索引 ] } **
同时,@,* 进行整个数组元素的索引方式,还是可以用的,
比如: ${array[@]} ,${array[*]}
不过,使用@,元素时列表的形式,但是,使用*,元素是字符串的形式
2> 求取数组的长度
在C中使用strlen( )函数
在Ruby中使用String.length方法获取字符串长度
在sh中使用 类似于VimScript的方式,进行数组的操作
${#array[@]},${#array[*]},即可获取到数组的长度
使用,(下标为N),${#array[N]},获取字符串的长度
3> 数组截取
数组,还可以截取吗?
答案是肯定的
数组进行截取的时候,遵循这样的操作规范
${array[X]:m:n}: m表示下标/索引/index
当X = */@ 时,表示,截取到从m个元素开始的n个元素
反之,表示,截取X元素从m开始的n个字符
这里,切不可理解为m~n个字符
var="helloworld"
echo ${#var}
echo ${var:0:2}
echo ${var:5:2}
var=('Crow' 'Sue')
echo ${var[@]:0:2}
echo ${var[@]:0:1}
echo ${var[@]:1:1}
echo ${var[1]:1:1}
4> 连接数组(拼接数组)
在其他语言中,合并数组,需要重新分配内存,使用for循环进行赋值,很是麻烦
在sh中,如下即可
name=("Crow" "Sue")
address=("Xi'an" "Shanghai")
other=(${name[@]} ${address[@]})
echo ${other[@]} #=> Crow Sue Xi'an Shanghai
所以,很是方便吧?
5> 替换元素
即改变数组中某个元素的值
讲道理,其实,直接进行赋值即可,但是,sh提供的方法,姑且看看吧.
array=(${array[@]/Crow/Evil})
即在数组全局中进行替换,这个特性,我不是很苟同
6> 取消数组/元素
同上理,使用unset可以取消,数组,变量,函数,全部可以取消
只读变量
这一部分也是很简单的
用法:将变量声明为只读属性,变成常量,避免滥用
declare -r a=5 --a,已经具有readonly属性
更简单地理解方式,const变量,,,
变量的作用域
这一部分内容,其实之前也是提到了很多次
作用域,即变量的有效作用范围,可以使用,被声明,被分配内存,可以访问的区域
在sh中,默认是全局变量(环境变量),这个全局指的是,这一个shell
在交互界面,就是这一个终端窗口,在脚本里,就是这一个脚本文件,都是有效范围
而C,是作为auto属性的自动变量,一般是函数中的局部变量,无链接
sh中的环境变量,有好有坏,进行程序设计时,各个函数间传参数很方便,很容易操纵,但同时
也有不小的弊端,,比如一些基本的临时变量,循环变量,这些i,j,k,如果进行模块化的开发
十分危险! ! !
有以下两种方法进行处理:
1.进行变量命名时,谨慎命名,命名为不易重复,含义明确的变量名
2.使用local命令,可以使变量的作用域局限在函数内部
看下面这个例子:
declare var
var=5
func_1()
{
var=6
echo "var = $var in func_1"
}
func_2()
{
var=8
echo "var = $var in func_2"
}
func_3()
{
local var=1000
echo "local var = $var in func_3"
}
func_1
func_2
func_3
转义和引用
其实转义和引用两个概念,我们平时已经很习惯的用了.
**转义: ** 因为一些预留的元字符,不能做为普通字符使用,所以进行转义,转义方法,就是使用 “ \ “
**引用: ** 引用是很常用的方法,转义时特殊的引用.
在sh中,引用,时为了防止字符串被解释为其他含义,常用的引用,双引号,单引号,反引号,反斜杠
1.双引号为部分引用
双引号,除了 $,`,\ 这是那种字符以外,都会被解释为普通字符
2.单引号为强引用
单引号,可以将一切解释为普通字符,但是单引号,最大的问题是,单引号,不能嵌套,否则会报错
3.反引号为命令替换
命令替换时十分重要的东西
命令替换,有什么用呢?
命令替换,可以将命令的结果保存至变量中,使用反引号即可,经常使用
同时,还另外一种命令替换 ** “ $ ( ) “ **
区别:反引号不清晰,且不能嵌套,所以建议使用$()的形式
同时,需要注意的一点:
在命令替换后,变量中保存的标准输出是没有换行符的,需要引用才能合理的显示
运算符
作为一门编程语言,怎么能少的了处理数据的内容呢?
sh中运算符,主要用于比较整数.所以这些运算符,也是以处理整数的运算为主
运算符,不多赘述,位运算符同理
sh中算术运算时基于let命令的
而且,一般情况下,运算符,数字是要紧紧相连的
要是不会,就是你特喵的C没学好,自己想办法补
其他的算术运算符
**1. 使用 $ [ ] **
$ [ ] 可以进行简单的算术运算
$ [ 1 + 1 ], $ [ 3 / 2 ]
2. 使用expr
expr时shell命令,可以进行算术运算,但是,运算符,数字不能紧紧相连的
否则会视为,字符串
3. 使用内建命令 declare
很多次看见这个命令了,同时它还可以进行算术运算
declare进行算术运算,其实是显示声明变量为整数, -i参数
还是要,紧紧相连,同时引用的变量不需要$,至直接使用
算术扩展
1. $ ( ( ) )
使用算术扩展符,可以进行变量和运算符的结合运算,不需要使用declare -i 声明
同时,如若其中的变量未初始化,则会将其视为0对待,但是,并不会真的赋值0
2. 使用bc运算
自行查看man文档,,(可以进行浮点运算的呦!)
我是华丽的分割线 ***********
分享在写Markdown时,千万不要
${#array[@]}, ${#array[N]}
这样的东西写在文本里,不然会把你逼疯得
转义,不存在的 !
December 6, 2017 1:06 AM