首页 >> 学习 >> Shell脚本编程基础 >> Shell变量:用户自定义变量
Shell变量:用户自定义变量

本节重要性:★★★★★    本节难度:★★★★★

Shell的变量包括用户自定义变量、位置变量、Shell预定义变量及环境变量等。这一节我们来学习自定义变量,剩下的几种变量在接下来的几节中分别学习。

1. 变量命名

Shell自定义变量的命名规则有以下几个:

另外,在Shell实际编程中,变量名应能从名字上看出变量内容的含义,如human_protein、plant_cds等,不建议使用tmp、var1、var_2等没有明显意义的变量名。

2. 变量赋值

Shell变量不需要定义,可以直接赋值,并且Shell是弱类型语言,变量没有整数型、字符型等类型的区分。

Shell变量赋值时,变量名前没有$,后面紧跟等号(=)及变量值,等号两侧不能有空白,这一点与其他语言有较大区别。

[peter@ibi-genome shell]$ plant=fern    #变量名前不能有$,=前后不能有空白
[peter@ibi-genome shell]$ plant = fern  #若=前有空白,Shell会将变量名解释为命令
bash: plant: command not found...
[peter@ibi-genome shell]$ $plant=fern   #若变量名前有$,Shell先进行变量替换,
将变量plant替换成其内容fern
bash: fern=fern: command not found...
[peter@ibi-genome shell]$ plant="seed plant"  #如果值里面有空格,需在两侧加引号

命令的执行结果也可以赋值给变量,即命令替换。命令替换有两种方法,反引号(``)或$( ):

[peter@ibi-genome shell]$ current_time=`date`
[peter@ibi-genome shell]$ echo $current_time
2017年 05月 02日 星期二 13:26:45 CST
[peter@ibi-genome shell]$ current_dir=$(pwd)
[peter@ibi-genome shell]$ echo $current_dir
/home/peter/shell

变量还可以从标准输入赋值:

[peter@ibi-genome shell]$ read animal   #回车后,Shell等待输入
dog
[peter@ibi-genome shell]$ echo $animal
dog

3. 数组

Bash的数组有以下特点:

数组赋值时可以单独给一个数组元素赋值,也可以将多个值一起赋值给数组:

[peter@ibi-genome shell]$ color[0]=red
[peter@ibi-genome shell]$ color=(red green blue)

4. 变量引用

(1)变量直接引用

简单变量直接引用时在变量名前加$即可,如

[peter@ibi-genome shell]$ color=red
[peter@ibi-genome shell]$ echo $color
red
[peter@ibi-genome shell]$ new_color=$color
[peter@ibi-genome shell]$ echo $new_color
red
[peter@ibi-genome shell]$ echo ${#new_color}     #变量的长度
3

(2)变量内容修改后引用

①变量内容删除 变量的内容可以使用通配符从头部或尾部删除部分内容。匹配时又分最短匹配和最长匹配两种。

变量设置方式    说明
${var#expr}      从变量内容前面删除到第一个符合的expr(最短匹配)
${var##expr}     从变量内容前面删除到最后一个符合的expr(最长匹配)
${var%expr}      从变量内容后面删除到最后一个符合的expr(最短匹配)
${var%%expr}     从变量内容后面删除到第一个符合的expr(最长匹配)

如下面的例子:

[peter@ibi-genome shell]$ path=/bin:/usr/bin:/usr/local/bin:/home/peter/bin
[peter@ibi-genome shell]$ echo $path
/bin:/usr/bin:/usr/local/bin:/home/peter/bin
[peter@ibi-genome shell]$ echo ${path#*:}
/usr/bin:/usr/local/bin:/home/peter/bin
# /bin:/usr/bin:/usr/local/bin:/home/peter/bin(从前面删除到第一个冒号)
[peter@ibi-genome shell]$ echo ${path##*:}
/home/peter/bin
# /bin:/usr/bin:/usr/local/bin:/home/peter/bin(从前面删除到最后一个冒号)
[peter@ibi-genome shell]$ echo ${path%:*}
/bin:/usr/bin:/usr/local/bin
# /bin:/usr/bin:/usr/local/bin:/home/peter/bin(从后面删除到最后一个冒号)
[peter@ibi-genome shell]$ echo ${path%%:*}
/bin
# /bin:/usr/bin:/usr/local/bin:/home/peter/bin(从后面删除到第一个冒号)

②变量内容部分替换 变量值将匹配到的内容替换成指定内容。

变量设置方式                 说明
${var/old_expr/new_expr}        将变量var的内容中第一个old_expr替换成new_expr
${var//old_expr/new_expr}       将变量var的内容中所有的old_expr替换成new_expr

如下面的例子:

[peter@ibi-genome shell]$ echo ${path/bin/BIN}
/BIN:/usr/bin:/usr/local/bin:/home/peter/bin     #第一个bin被替换
[peter@ibi-genome shell]$ echo ${path//bin/BIN}
/BIN:/usr/BIN:/usr/local/BIN:/home/peter/BIN     #所有的bin被替换

③变量内容整体替换 根据变量是否赋值和是否为空决定变量被引用的值。

变量设置方式     a没有设置        a为空字符串     a为非空字符串
b=${a-str}         b=str             b=               b=$a
b=${a:-str}        b=str             b=str            b=$a
b=${a+str}         b=                b=str            b=str
b=${a:+str}        b=                b=               b=str
b=${a=str}         a=str             a不变            a不变
                   b=str             b=               b=$a
b=${a:=str}        a=str             a=str            a不变
                   b=str             b=str            b=$a
b=${a?str}         str => stderr     b=               b=$a
b=${a:?str}        str => stderr     str => stderr    b=$a

上述变量设置方式当中,+和-只影响变量b的值,=还会影响变量a的值,而?会根据变量a的值显示提示信息。上表内容太多,很难记得住,我们只需了解这种变量替换方式,如果写程序遇到这种需求,查一下该表就可以了。

另外,变量b经常跟变量a是同一个变量,也就是用来根据一个变量是否为空然后赋值。

(3)数组引用

数组元素可以单独引用,整个数组也可以一起引用。另外,我们可以方便的引用数组元素的个数或数组元素的长度。

数组引用方式                        说明
${array[i]}                             数组array第i个元素
${array[*]}  或 ${array[@]}             数组array所有的元素
${#array[i]}                            数组array第i个元素的长度
${#array[*]}、${#array[@]} 或 ${#array} 数组array元素的个数

如:

[peter@ibi-genome shell]$ flower=(lily "Chinese rose" tulip)
[peter@ibi-genome shell]$ echo ${flower[1]}
Chinese rose
[peter@ibi-genome shell]$ echo ${flower[*]}
lily Chinese rose tulip
[peter@ibi-genome shell]$ echo ${#flower[1]}
12
[peter@ibi-genome shell]$ echo ${#flower[@]}
3

上面的${array[*]}和${array[@]}在使用时有一些区别,使用双引号时,"${array[*]}"扩展成由空格将数组元素连接成的一个字符串,而"${array[@]}"扩展成多个词,每个数组元素是一个词。如果不用双引号,两种方式都扩展成多个词,并且数组元素中的空格也作为词的分隔符。如我们用for循环输出上面的数组:

[peter@ibi-genome shell]$ for i in "${flower[*]}";do echo $i;done
lily Chinese rose tulip
[peter@ibi-genome shell]$ for i in "${flower[@]}";do echo $i;done
lily
Chinese rose
tulip
[peter@ibi-genome shell]$ for i in ${flower[*]};do echo $i;done
lily
Chinese
rose
tulip
[peter@ibi-genome shell]$ for i in ${flower[@]};do echo $i;done
lily
Chinese
rose
tulip

for循环我们在后面的控制结构中还会详细学习。不用引号时${flower[*]}和${flower[@]}中的第1个元素"Chinese rose"都扩展成了两个词。

5. 变量输出

Shell变量输出可以用echo或printf命令。echo命令比较简单,我们前面已经学习过。printf是格式化输出,语法与C语言的printf一致。如:

[peter@ibi-genome shell]$ a=10
[peter@ibi-genome shell]$ echo $a
10
[peter@ibi-genome shell]$ printf "%d\n" $a
10
[peter@ibi-genome shell]$ printf "%.2f\n" $a
10.00

6. 变量删除

如果一个变量不再使用,可以用unset命令删除。但如果该变量已经用readonly命令定义为只读变量,则不能用unset删除。

[peter@ibi-genome shell]$ echo $color
red
[peter@ibi-genome shell]$ unset color
[peter@ibi-genome shell]$ echo $color

Shell变量使用比较灵活,尤其是变量内容删除和替换,在编程实践中善于利用可提高编程效率。但Shell的语法要求很严,与Perl宽松的语法形成鲜明对比。

<<上一节  下一节>>