主要内容
环境变量
shell中包括两种类型的变量:全局变量和局部变量。局部变量只适用于当前shell,而环境变量是全局的,它适用于所有当前shell以及其派生出来的任意子进程。
变量的创建
shell变量是在赋值的同时一起创建的,无需事先声明。
例如:
1 |
var='hello' |
需要注意的是, 等号两边不能够有空格,否则会出错。要使用这个变量,只需要在它的名称前面添加一个“$”符号。
例如:
1 |
echo $var |
动态设置变量值
很多时候,我们需要由用户输入变量的值。使用read命令可以达到这个目的。
例如:
1 2 |
#创建一个变量var,并等待用户输入 read var |
运行该命令之后,终端会等待用户的输入,一旦用户输入完毕,var变量就拥有一个值。同样地,运行该命令之前,不需要事先声明var变量。
read命令还可以输出提示信息,只需要使用”-p“参数。例如:
1 2 3 4 |
[normal@study ~]$ read -p "Please enter something: " var2 Please enter something: the second variable [normal@study ~]$ echo $var2 the second variable |
变量的销毁
使用unset命令销毁已定义的用户变量,全局变量不能unset。
1 2 3 4 5 |
#定义变量var var="value" #销毁变量 unset var |
使用引号
shell命令中既可以使用单引号也可以使用双引号,不同的是,双引号中可以使用变量,而单引号中的内容将会原样输出。
例如:
1 2 3 4 5 |
[root@study ~]# var1='hello' [root@study ~]# var2='world' [root@study ~]# var="${var1} ${var2}" [root@study ~]# echo $var hello world |
而如果使用单引号的话,结果是:
1 2 3 |
[root@study ~]# var='${var1} ${var2}' [root@study ~]# echo $var ${var1} ${var2} |
转义字符 \
某些字符具有特殊用途,某些时候如果想输出特殊字符,需要使用“\“转义。
例如
1 2 |
[root@study ~]# echo "\${var1}+\${var2}=${var1} ${var2}" ${var1}+${var2}=hello world |
set、env、export和declare
set
set命令有多个作用,例如改变shell的行为,设置shell的位置参数,显示shell的变量值。
例如之前的:set +o noclobber ,该选项用于设置符号”>”的行为,是覆盖已存在文件还是抛出错误。
不带参数的set命令用于列出当前shell的所有变量。
env
不带参数的env命令打印当前的环境变量;否则env命令为当前执行的命令设置环境变量。
例如:
1 2 |
#为程序program设置环境变量name和name2 env name=value name2=value2 program [args] |
name和name2都是可选的,默认使用当前的环境变量,可以通过-i参数忽略环境变量。
export
export命令可以把局部变量设置为全局变量。
例如:
1 |
export $JAVA_HOME=/user/share/java |
declare
declare命令可以用来声明变量的类型。例如数组,整型。
例如:
1 2 3 |
[normal@study ~]$ var=1+2 [normal@study ~]$ echo $var 1+2 |
默认情况下,shell的变量类型都是字符串,因此,字符串是不能进行运算的。通过declare,可以把变量定义为指定的类型:
1 2 3 |
[normal@study ~]$ declare -i var=2+3 [normal@study ~]$ echo $var 5 |
还有数组类型:
1 2 3 4 5 6 |
[normal@study ~]$ declare -a arr [normal@study ~]$ arr[1]='h' [normal@study ~]$ arr[2]='e' [normal@study ~]$ arr[3]='l' [normal@study ~]$ echo ${arr[1]} h |
除此之外,declare还有export的作用
通过declare -x命令,可以把变量导出为全局变量,相反,通过+x参数撤销该变量的导出。
常用的内置变量
- $HOME:用户的家目录
- $PATH:命令的搜索目录列表
- $PS1: 命令提示符
- $PS2: 二级提示符
- $IFS: 内部字段分隔符
- $0: 当前运行的脚本名字(程序名称)
- $#: 传递给脚本的参数个数
- $$: shell脚本的进程号
- $?: 上一条shell命令的返回值(是否正常运行)
- $1, $2: 脚本程序的参数 (超出9个参数,第10个参数需要使用{}括起来,例如${10} )
- $*: 所有的参数,通过$IFS定义的分隔符分开
- $@:$*的变体,但它不使用IFS变量,即使IFS为空,参数也不会挤在一起
这里重点说一下内部分隔符$IFS,如果对它不了解,在编写脚本的时候就有可能会犯一些不必要的错误,主要体现在命令参数的处理上面。
默认的shell内部分隔符是空格、tab或者新行’\n’。如果shell在将要处理的数据中找到这些符号,它就假设一个新数据字段的开始。例如:
1 2 3 4 5 6 7 8 9 |
[normal@study ~]$ IFS='' [normal@study ~]$ set foo bar bam [normal@study ~]$ echo "$@" foo bar bam [normal@study ~]$ echo "$*" foobarbam [normal@study ~]$ unset IFS [normal@study ~]$ echo "$*" foo bar bam |
$*和$@还有不同的地方,当它们有引号括起来的时候,它们对参数的解析不同,例如:
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/bin/sh for var in "$*" do echo $var done echo +++++++++++++++++++++++++++++ for var in "$@" do echo $var done |
输出结果是:
1 2 3 4 5 6 |
[normal@centos7-server ~]$ ./lsvar.sh 1 2 3 1 2 3 +++++++++++++++++++++++++++++ 1 2 3 |
也就是说,当有引号括起来的时候,$*会把参数当成一个处理,而$@则依然把它们区分对待。
如果没有使用引号,两者对参数的处理行为基本一样。
array变量
变量的声明有多种方式上面declare中的方式显然不是最好的。实际上,declare的时候,可以直接列出数组中的成员,例如:
1 |
declare -a Fruits=(Apple Mango Orange Banana) |
当然declare -a
也可以省略:
1 |
Fruits=(Apple Mango Orange Banana) |
索引
数组的索引从0开始,和一般的编程语言相同
1 2 3 4 5 |
Fruits=(Apple Mango Orange Banana) echo ${Fruits[0]} #Apple echo ${Fruits[1]} #mango echo ${Fruits[2]} #Orange echo ${Fruits[3]} #Banana |
获取数组所有成员
通过数组索引可以获取数组的单个成员,要获取数组的所有成员,则需要使用*
或者@
符号。
1 2 3 4 5 |
#!/bin/bash Fruits=(Apple Mango Orange Banana) echo ${Fruits[@]} echo ${Fruits[*]} |
获取数组长度
shell通过#
符号获取数组的长度,同时适用于获取数组成员的长度
1 2 3 4 5 6 7 8 9 |
#!/bin/bash Fruits=(Apple Mango Orange Banana) #数组的长度 echo "Length of Fruits: " ${#Fruits[@]} #Apple的字符个数 echo "Length of Fruits[0]: " ${#Fruits[0]} |
数组的查找和替换
语法:
1 |
${ArrayName[@]/Search/Replacement} |
1 2 3 4 5 6 |
#!/bin/bash Fruits=(Apple Mango Orange Banana Grapes Watermelon); #查找Grapes并使用Strawberry替换,最后打印数组内容 echo ${Fruits[@]/Grapes/Strawberry} |
数组复制
通过圆括号实现数组的复制,语法:
1 |
arrayName2=(${arrayName1[@]}) |
通过圆括号实现数组的复制
实例:
1 2 3 4 |
#!/bin/bash Fruits=(Apple Mango Orange Banana) newFruits=(${Fruits[@]}) echo ${newFruits[@]} |
数组切片
1 2 3 4 |
#!/bin/bash Fruits=(Apple Mango Orange Banana Grapes Watermelon); echo ${Fruits[@]:2:3} |
从数组第二个位置开始,切取3个元素。
结果:
1 |
Orange Banana Grapes |
也可以对数组的成员进行切片操作:
1 2 3 4 |
#!/bin/bash Fruits=(Apple Mango Orange Banana Grapes Watermelon); echo ${Fruits[4]:2:3} |
结果:
1 |
ape |
添加元素到数组
1 2 3 4 5 6 7 |
#!/bin/bash Fruits=(Apple Mango Orange Banana Grapes Watermelon); Fruits=(${Fruits[@]} Blackberry Blueberry) echo "${Fruits[@]}" |
转载请注明:Pure nonsense » shell程序设计(二)shell变量