分享

shell浅谈之一变量和引用

 笑观云卷云舒 2016-09-04

一、简介

       变量是脚本语言的核心,shell脚本又是无类型的。变量本质上存储数据的一个或多个计算机内存地址,分为本地变量(用户当前shell生命期使用,随shell进程的消亡而无效,类似局部变量)、环境变量(适用于所有由登录进程所产生的子进程)和位置参数(向shell脚本传递参数,只读)。而shell使用变量就需要引用,它们密切相关。

二、详解

1、变量赋值      

(1)变量赋值规则:等号两边不能有空格、value值包括空格必须用双引号、变量名只能包括字母数字和下画杠,并变量名不能以数字开头。

(2)如果value值中有空格,需要用双引号引以来。variable="hello world"。

(3)unset命令清除变量的值。

(4)变量赋值模式

(5)readonly将变量设置为只读,只读变量不能再次进行赋值操作。

2、无类型的变量

(1)C中定义变量需要声明整型、浮点型、字符型等,而shell脚本变量却是无类型的。shell不支持浮点型只支持整型和字符型,同时字符型还具有一个整型值0(判断标准:变量中只包含数字是数值型其他是字符串)。

  1. #!/bin/bash  
  2.   
  3. a=2009  
  4. let "a+=1"  
  5. echo "a=$a"  
  6.   
  7. b=xx09  
  8. echo "b=$b"  
  9. declare -i b  
  10. echo "b=$b"  
  11.   
  12. let "b+=1"  
  13. echo "b=$b"  
  14.   
  15. exit 0  

(2)位置参数

从命令行向shell脚本传递参数,$0表示脚本的名字,$1代表第一个参数,以此类推。从${10}开始参数号需要用花括号括起来。

  1. #!/bin/sh  
  2. echo "The script name is: $0"            #$0表示脚本本身  
  3. echo "Parameter #1:$1"  
  4. echo "Parameter #2:$2"  
  5. echo "Parameter #3:$3"  
  6. echo "Parameter #4:$4"  
  7. echo "Parameter #5:$5"  
  8. echo "Parameter #6:$6"  
  9. echo "Parameter #7:$7"  
  10. echo "Parameter #8:$8"  
  11. echo "Parameter #9:$9"  
  12. echo "Parameter #10:${10}"           #用大括号括起来  
  13.   
  14. echo "-------------------------"  
  15. echo "All the command line parameters are: $*"  
特殊的位置参数:

3、内部变量

内部变量指能够对bash shell脚本行为产生影响的变量,属于环境变量的范畴。

(1)BASH

      BASH记录了shell的路径,通常是/bin/bash。内部变量SHELL是通过BASH的值确定当前Shell的类型,linux使用的是bash shell,因而两个变量的值都是/bin/bash。

(2)BASH_VERSINFO

它是一个包含6个元素的数组,这些元素用于表示bash的版本信息。

  1. #!/bin/bash  
  2.   
  3. for n in 0 1 2 3 4 5  
  4. do  
  5.   echo "BASH_VERSINFO[$n]=${BASH_VERSINFO[$n]}"  
  6. done  

BASH_VERSINFO[0]表示bash shell的主版本号,BASH_VERSINFO[1]表示shell的次版本号,BASH_VERSINFO[2]表示shell的补丁级别,BASH_VERSINFO[3]表示shell的编译版本,BASH_VERSINFO[4]表示shell的发行状态,BASH_VERSINFO[5]表示shell的硬件架构。

(3)BASH_VERSION

linux系统的bash shell版本包含主次版本、补丁级别、编译版本和发行状态,即BASH_VERSINFO数组取值为0~4。显示BASH_VERSION的值。


(4)DIRSTACK
      它显示目录栈的栈顶值。linux目录栈用于存放工作目录,便于程序员手动控制目录的切换,bash shell定义了两个系统命令pushd(将某目录压入目录栈并将当前工作目录切换到入栈的目录)和popd(将栈顶目录弹出并将当前工作目录切换到栈顶目录)来维护目录栈。

      DIRSTACK记录栈顶目录值,初值为空。linux还有一个命令dirs用于显示目录栈的所有内容。

(5)GLOBIGNORE

     它是由冒号分隔的模式列表,表示通配时忽略的文件名集合。一旦GLOBIGNORE非空,shell会将通配得到的结果中符合GLOBIGNORE模式中的目录去掉。例如ls a*列出当前目录以a开头的文件,设置GLOBIGNORE=“ar*”,再次执行ls a*将剔除以ar开头的文件。

(6)GROUPS

      GROUPS记录了当前用户所属的群组,linux的一个用户可同时包含在多个组内,GROUPS是一个数组记录了当前用户所属的所有群组号。管理用户组的文件是/etc/group,格式:群组名:加密后的组口令:群组号:组成员,组成员(组成员列表)。

(7)HOSTNAME

      HOSTNAME记录了主机名,linux主机名是网络配置时必须要设置的参数,可在/etc/sysconfig/network文件中设置主机名。/etc/hosts文件用于设定IP地址和主机名之间的对应关系,可快速从主机名查找IP地址。

(8)HOSTTYPE和MACHTYPE

都用于记录系统的硬件架构,它们与BASH_VERSINFO[5]等值


(9)OSTYPE

记录操作系统类型,linux系统中,$OSTYPE=linux。

(10)REPLY

      REPLY变量与read和select命令有关。read用于读取标准输入(stdin)的变量值,read variable将标准输入存储到variable变量中,而read将读到的标准输入存储到REPLY变量中。

     select脚本:

  1. #!/bin/bash  
  2. echo "Pls. choose your profession?"  
  3. select var in "Worker" "Doctor" "Teacher" "Student" "Other"  
  4. do  
  5.    echo "The \$REPLY is $REPLY."    
  6.    echo "Your preofession is $var."  
  7. break  
  8. done  

”#?"提示符由shell提示符变量PS3进行设置(#?是其默认值)。修改export PS3="your choice:"。REPLY变量值为用户选择的序号,var变量为REPLY序号所对应的字符串。

(11)SECONDS

SECONDS记录脚本从开始执行到结束所耗费的时间(单位为秒)。调试性能时比较有用。

  1. #!/bin/bash  
  2. count=1  
  3. MAX=5  
  4.   
  5. while [ "$count" -le "$MAX" ];do  
  6.   echo "This is the $count time to sleep."  
  7.   let count=$count+1  
  8.   sleep 1  
  9. done  
  10.   
  11. echo "The running time of this script is $SECONDS"  

(12)SHELLOPTS

它记录了处于开状态的shell选项列表,它是一个只读变量。Shell选项用于改变Shell的行为,Shell选项有开和关两种状态,set命令用于打开或关闭选项。set -o optionname(打开名为optionname选项),set +o optionname(关闭名为optionname选项)。比如打开interactive(交互模式运行)可以使用set -o interactive或set -i等价。Shell选项有很多。

(13)SHLVL

       记录Shell嵌套的层次,启动第一个shell时,$SHLVL=1,若在这个Shell中执行脚本,脚本中的SHLVL为2,脚本中再执行子脚本,SHLVL就会递增。

(14)TMOUT

用于设置Shell的过期时间,TMOUT不为0时,shell会在TMOUT秒后将自动注销,TMOUT放在脚本中可以规定脚本的执行时间。

  1. #!/bin/bash  
  2.   
  3. TMOUT=3  
  4. echo "What is your name?"  
  5. read fname  
  6.   
  7. if [ -z "$fname" ]; then  
  8.    fname="(no answer)"  
  9. fi  
  10.   
  11. echo "Your name is $fname"  

用户有输入,脚本执行read后的程序,用户没有输入等待TMOUT秒后执行read后程序但fname会为空。

4、有类型变量

    Shell变量一般是无类型的,bash shell提供了declare和typeset两个命令用于指定变量的类型(它们完全等价)。declare [选项] 变量名,有6个选项。

declare命令-r选项将变量设置成只读属性,与readonly命令一样,变量值不允许修改。

declare命令-x选项将变量声明为环境变量,相当于export,但declare -x允许声明环境变量同时给变量赋值,而export不支持。

declare -i将变量定义为整型数,不能再按字符串形式处理改变量(和let命令进行算术运算一样,expr命令可以替换let命令)。

  1. #!/bin/bash  
  2. variable1=2009  
  3. variable2=$variable1+1  
  4. echo  "variable2=$variable2"  
  5. let variable3=$variable1+1  
  6. echo  "variable3=$variable3"  
  7. declare -i variable4  
  8. variable4=$variable1+1  
  9. echo  "variable4=$variable4"  

      再介绍一种变量执行算术运算的方法:双圆括号即((...))格式。result=$((var1*var2));var1和var2执行乘法运算。双圆括号也可以使shell实现C语言风格的变量操作。

  1. #!/bin/bash  
  2. ((a = 2014))  
  3. echo "The initial value of a is:$a"  
  4. ((a++))  
  5. echo "After a++,the value of a is:$a"  
  6. ((++a))  
  7. echo "After ++a,the value of a is:$a"  
  8. ((a--))  
  9. echo "After a--,the value of a is:$a"  
  10. ((--a))  
  11. echo "After --a,the value of a is:$a"  

      双圆括号实现五种C语言风格的运算,自增自减是shell算术运算符中未曾定义过的,是C语言中的相关内容。a = 2014,C语言允许赋值两端有空格但shell不允许。双圆括号还可以实现更加复杂的C语言的运算如逻辑判断、三元操作等。

5、间接变量引用

      该引用不是将变量引起来,而是理解为:如果第一个变量的值是第二个变量的名字,从第一个变量引用第二个变量的值就称为间接变量引用。bash shell提供了两种格式实现间接变量引用:eval tempvar=\$$variable和tempvar=${!variable},其中eval是关键字,用\$$形式得到variable的简介引用,用${!...}得到variable的间接引用。

  1. #!/bin/bash  
  2. variable1=variable2  
  3. variable2=Hadoop  
  4. echo "varialbe1=$variable1"  
  5.   
  6. eval tempvar=\$$variable1  
  7. echo "tempvar=$tempvar"  
  8.   
  9. echo "Indirect ref variable1 is :${!variable1}"  

例:使用间接变量引用实现数据库表格的查找:

  1. #!/bin/bash  
  2.   
  3. S01_name="Li Hao"  
  4. S01_dept=Computer  
  5. S01_phone=025-83481010  
  6. S01_rank=5  
  7.   
  8. S02_name="Zhang Ju"  
  9. S02_dept=English  
  10. S02_phone=025-83466524  
  11. S02_rank=8  
  12.   
  13. S03_name="Zhu Lin"  
  14. S03_dept=Physics  
  15. S03_phone=025-83680010  
  16. S03_rank=3  
  17.   
  18. PS3='Pls. select the number of student:'  
  19. select stunum in "S01" "S02" "S03"  
  20. do  
  21.   name=${stunum}_name  
  22.   dept=${stunum}_dept  
  23.   phone=${stunum}_phone  
  24.   rank=${stunum}_rank  
  25.   
  26.   echo "BASIC INFORMATION OF NO.$stunum STUDENT:"  
  27.   echo "NAME:${!name}"  
  28.   echo "DEPARTMENT:${!dept}"  
  29.   echo "PHONE:${!phone}"  
  30.   echo "RANK:${!rank}"  
  31.   break  
  32. done  
      在间接变量引用中,第一个变量中存放的是最终值的地址,因此,间接变量引用使得shell编程实现了类似于C语言中指针的功能,在很多场合能够精简shell脚本。

6、引用

(1)引用指将字符串用引用符号引起来,以防止特殊字符被shell脚本重解释为其他意义。shell中定义了四种引用符号。

(2)双引号和单引号

       双引号引用除美圆符号($)、反引号(`)和反斜线(\)之外的所有字符,即$和`及\在双引号中仍被解释为特殊意义,利用双引号引用变量能防止字符串分割,而保留变量中的空格。因此双引号的引用方式称为部分引用。


        单引号中字符除单引号本身之外都解释为字面意义,不再具备引用变量的功能,单引号的引用方式称为全引用。

  1. #!/bin/bash  
  2. echo "Why can't I write 's between single quotes"  
  3.   
  4. echo 'Why can'"'"'t I write' "'"'s between single quotes'  
(3)反引号

反引号进行命令替换(将命令的标准输出作为值赋给某个变量),等价于$(),同时$()形式的命令替换是可以嵌套的。如`pwd`和$(pwd)等价都为当前工作目录。

反引号与$()在处理双反斜线时存在区别,反引号将反斜线符号处理为空格,而$()符号将其处理为单斜线符。


7、转义

(1)反斜线符号(\)表示转义,将屏蔽下一个字符的特殊意义,而以字面意义解析它。


  1. #!/bin/bash  
  2.   
  3. variable="(]\\{}\$\""  
  4. echo $variable  
  5. echo "$variable"  
  6.   
  7. IFS='\'  
  8. echo $variable  
  9. echo "$variable"  
  10. exit 0  

(2)转义符除了屏蔽特殊字符的特殊意义外,加上一些字母能够表达特殊的含义。

  1. #!/bin/bash  
  2.   
  3. #echo不加e选项,按照字面含义解释\t等特殊符号  
  4. echo "\t\n\a\v"  
  5.   
  6. #echo加上e选项后,按照特殊含义解释这些特殊符号  
  7. echo -e "\t\t\t\thello"  
  8. echo $'\t\thello'  
  9.   
  10. echo -e "hello\v\v\v\vhello"  
  11. echo -e "\a\a\a\a"  
  12. echo -e "\042"  

$''与-e选项等价。

(3)echo加-n选项表示输出文字后不换行,不带-n默认是输出文本后自动换行。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多