变量

变量是能储存计算结果或能表示值抽象概念。变量可以通过变量名访问。

变量声明

声明变量一般使用下面方式:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# var=test #这里声明了一个名为 var 的变量,并给他赋值为test
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# # “=”前后不能有空格,变量名区分大小写

或者下面方式:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# declare var1=123
root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# export var2=234
root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# 
root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# env var3=333

上面使用的命令:declare,export,env 都可以声明变量,区别在于变量作用域不同。 shell有两种变量:

  • shell局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。 通过赋值语句定义好的变量,可以通过如下方法定义shell变量 root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# declare var1=123 root@iZuf6ilzd4iqvuj4dvuiwtZ:~/HtmlDOM/Libs# var1=123

  • 用户环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。 通过export语法导出的shell私有变量,可以通过如下方法导出用户环境变量 export x =2 declare -x x=2

变量使用

显示shell变量

  • env 这是一个工具,或者说一个Linux命令,显示用户的环境变量。
  • set 显示用户的局部变量和用户环境变量。
  • export 显示导出成用户变量的shell局部变量,并显示变量的属性;就是显示由局部变量导出成环境变量的那些变量 (比如可以 export WWC导出一个环境变量,也可通过 declare -X LCY导出一个环境变量)
  • declare 跟set一样,显示用户的shell变量 (局部变量和环境变量)

declare命令:

    # 语法:declare [-aAfFgilnrtux] [-p] [name[=value] ...]
    # 描述: declare 用来声明变量和配置变量的属性,如果declare后面没有参数,将会显示全部变量的属性和值。
    # 参数
				-f	 限制行动或显示函数名称和定义
				-F	只限制显示函数名(加上行号和源文件时调试)
				-g	在shell函数中使用时创建全局变量;否则忽略
				-p	显示每个变量的属性和值。

    # 属性设置参数
				-a	声明一个索引数组
				-A	声明一个聚合数组
				-i	 变量值为整数,当给变量赋值为非整数值时变量为0
				-l	 给变量赋值时转换成小写字母
				-n	将名称引用为其值命名的变量。
				-r	 只读变量 # 使用readonly命令也可以设置变量只读
				-t	使名称具有“trace”属性
				-u	给变量赋值时转换成大写字母
				-x	导出变量到用户环境变量

export命令

    # 语法: export [-fn] [name[=value] ...] or export -p
	# 描述:从shell变量导出属性,将自动导出的每个名称标记为随后执行的命令的环境。如果提供了值,则在导出之前分配值。
    # 参数
	 -f 	引用shell函数
     -n	    从每个变量删除导出属性
     -p     显示已导出的函数和变量清单

set 命令

    # 语法:set [-abefhkmnptuvxBCHP] [-o option-name] [--] [arg ...]
    # 描述:设置或取消shell参数和位置参数的值。更改shell属性和位置参数的值,或显示shell变量的名称和值。

    # 参数:
      -a  标记为导出而修改或创建的变量。
      -b  立即通知终止任务。
      -e  如果有非零状态的命令退出,立即退出。
      -f  禁用文件名称生成(全局)。
      -h  记住所查找的命令位置。
      -k 所有的赋值参数都放置在一个命令的环境中,而不仅仅是在命令名前面的命令。
      -m  开启任务控制。
      -n  读取命令,但不执行它们。
      -o option-name
          设置对应于选项名的变量:
              allexport    与-a相同
              braceexpand  与-B相同
              emacs        使用emacs样式的行编辑界面。
              errexit      与-e相同
              errtrace     与-E相同
              functrace    与-T相同
              hashall      与-h相同
              histexpand   与-H相同
              history      开启命令历史
              ignoreeof    读取EOF时shell不会退出
              interactive-comments
                           允许注释出现在交互式命令行中
              keyword      same as -k
              monitor      same as -m
              noclobber    same as -C
              noexec       same as -n
              noglob       same as -f
              nolog        目前接受但忽略
              notify       same as -b
              nounset      same as -u
              onecmd       same as -t
              physical     same as -P
              pipefail     管道的返回值是最后一个以非零状态退出的命令的状态,如果没有非零状态的命令退出,则为零。
              posix        更改bash的行为,默认操作与Posix标准不同,以匹配标准。
              privileged   same as -p
              verbose      same as -v
              vi           使用vi样式的行编辑界面
              xtrace       same as -x
      -p  当真实有效的用户id不匹配时打开。取消对$ENV文件的处理和shell函数的导入。关闭这个选项会导致有效的uid和gid设置为真正的uid和gid。
      -t  读取和执行一个命令后退出。
      -u  在替换时将未设置的变量视为一个错误。
      -v  打印shell的输入行。
      -x  打印命令及其执行时的参数。
      -B  shell将执行支撑扩展
      -C  如果设置,则不允许通过重定向输出来覆盖现有的常规文件。
      -E  如果设置,ERR捕获是由shell函数继承的。
      -H  启用!风格历史替换。当shell是交互式的时,这个标志是默认的。
      -P  如果设置,在执行命令(例如更改当前目录的cd)时,不要解析符号链接。
      -T  如果设置,DEBUG捕获从shell函数继承
      --  将剩余的参数分配给位置参数。如果没有剩下的参数,那么位置参数就没有设置。
      -   将剩余的参数分配给位置参数。-x和-v选项关闭。

env命令

    # 描述: 在修改的环境中运行程序,将每个名称设置为环境中的值并运行命令。对长参数的强制参数也必须是短参数。
    # 语法: env [OPTION]... [-] [NAME=VALUE]... [COMMAND [ARG]...]
    # 参数
        -i, --ignore-environment
              从一个空的环境开始。

        -0, --null
              用NUL,而不是newline结束每个输出行。

        -u, --unset=NAME
              从环境中删除变量。

    # 如果没有参数则打印当前环境中的变量

变量作用域

shell变量

shell变量相当于一个全局变量,可以在子shell,函数中使用。在函数中直接声明一个变量或者使用declare -g 声明变量,则此变量为全局变量。

如:

# variable=value
# declare variable=value

函数变量

使用local命令可以声明一个函数(局部)变量,此变量只能在函数内访问,如果不适用local命令,则此变量为shell(全局)变量。

function test(){
    variable=123; # 全局变量
    declare -g v=2 # 全局变量
    local a=123 # 函数(局部)变量,只能在函数内访问
}

变量取消

使用unset命令可以删除变量

unset命令

    # 语法: unset [-f] [-v] [-n] [name ...]
    # 描述: 撤销shell变量和函数的值和属性。对于每个名称,删除相应的变量或函数。
    # 参数:
        -f  将name参数视为函数
        -v	将name参数视为变量
        -n	每个名称视为一个名称引用,并将变量本身设置为unset。而不是它引用的变量。
        # 没有选项,unset首先尝试取消设置一个变量,如果失败,则尝试取消设置一个函数。
        # 注意:只读变量不能被unset
        root@iZuf6ilzd4iqvuj4dvuiwtZ:~# declare -r NAME=raojl
        root@iZuf6ilzd4iqvuj4dvuiwtZ:~# unset NAME
        -bash: unset: NAME: cannot unset: readonly variable
        root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

变量调用

在声明变量一个变量时变量名称要遵守下列规则:

  1. 不能以特殊字符(除了_),数字,美元符($)开头
  2. 变量名不能是纯数字
  3. 变量名可以是英文或数字或特殊字符(_)的组合

调用变量时在变量明前面以$var的形式调用变量,如:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# name=raojl # 声明一个名为name的变量并赋值为raojl
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo $name # 调用变量name
raojl  # name的值
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

变量名可以在双引号""内使用,shell会解释引号内的变量,在''则不会解释变量。如:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# name=raojl
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "$name" # shell会解释引号内的变量name
raojl # 变量name的值
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo '$name' # shell不会解释name
$name # 原样输出,不会解释
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

也可以使用大括号${variable}的形式将变量包裹起来,为了避免变量名被其他字符干扰,可以使用此方式,如:

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# hello=Hello
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "$helloWorld" # shell将会解释变量 hellworld

root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "${hello}World" # shell将会解释hello变量
HelloWorld
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo "$hello World" 
Hello World
root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

$符号引入了参数扩展、命令替换或算术扩展。要扩展的参数名称或符号可以用括号括起来,这是可选的,但可以保护变量,使其从可以被解释为名称的一部分的字符中扩展。

参数扩展

       ${parameter}
              参数的值被替换。当参数是一个超过一个数字的位置参数时,或者在参数后面加上一个不被解释为其名称的部分的字符时,需要使用括号。参数是一个
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH}
                /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:-word}
              使用默认值,如果parameter未定义或值为空则被替换成word,否则为parmeter的值
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:-w} #PATH不为空
                /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PAT:-w} # PAT为空
                w
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:=word}
              给parameter赋值默认值,如果parameter为空或未定义,则将word赋值给parmaeter,否则值不变,parameter的值不变。特殊字符和位置参数不适用
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PAT:=w}
                w
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PAT}
                w
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:=W}
                /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

    
       ${parameter:?word}
              如果parameter未定义或为空,则在输出(标准错误)一个错误word,否则输出parameter的值
               列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${P:?ERROR} # P未定义
                -bash: P: ERROR
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:+word}
              使用替代值.  如果parameter 为空或未定义,输出为空,否则输出word
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${P:+ERROR}
                
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:+ERROR}
                ERROR
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter:offset}
       ${parameter:offset:length}
              子字符串扩展,从offset位置开始,输出length个字符
            如果偏移量计算为小于零的数,则该值用作参数值结束时字符的偏移量。
            如果长度对小于零的数求值,则将其解释为从参数值(而不是多个字符)结
            束字符的偏移量,而扩展是偏移量与结果之间的字符。注意,一个负偏移
            量必须与冒号隔开至少一个空间。
                如果length未指定,则0-offset位置的字符将会被删除
              如果参数是@,那么结果就是长度位置参数开始偏移。相对于最大的位
              置参数,一个负偏移量被取走,所以-1的偏移量等于最后一个位置参数
              。如果长度计算为小于零的数,则为扩展误差。

              
              如果参数是由@或*编写的索引数组名,则结果是数组的长度成员以${pa
              rameter[offset]}开始。相对于指定数组的最大索引,将使用一个负偏
              移量。如果长度计算为小于零的数,则为扩展误差。

              应用于关联数组的子字符串扩展会产生未定义的结果。

              子字符串索引是从零开始的,除非使用了位置参数,在这种情况下,在
              默认情况下,索引从1开始。如果偏移量为0,并且使用了位置参数,$0
              将被预先固定到列表中。
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:2}
                sr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH:2:4}
                sr/l
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${!prefix*}
       ${!prefix@}
              变量名匹配,匹配以prefix开头的变量名,输出匹配的变量名
              列:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${!P*}
                PAT PATH PIPESTATUS PPID PS1 PS2 PS4 PW PWD
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${!P@}
                PAT PATH PIPESTATUS PPID PS1 PS2 PS4 PW PWD
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${!name[@]}
       ${!name[*]}
              数组键的列表。如果名称是一个数组变量,则扩展到名称中指定的数组
              索引(键)列表。如果名称不是数组,则将其扩展为0,如果名称设置为n
              ull,则为null。当使用@时,扩展出现在双引号,每个键扩展到一个单独的单词。
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${name[@]}
                    1 2
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${!name[@]}
                    0 2
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${#parameter}
              变量长度,如果变量未定义或为空则返回0,如果是一个数组变量则返回数组长度
              例如:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${#PATH}
                60
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter#word}
       ${parameter##word}
              前缀匹配模式,如果parameter的值以word开头则parameter前的word将会被删除,如果parameter是一个数组变量,形如${parameter[@]#word},则此数组中的每个值将会与word做前缀匹配
              
              #word 为最短匹配
              ##word 为最长匹配
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH#/usr}
                    /local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 
       ${parameter%word}
       ${parameter%%word}
              与${parameter#word}相反,后缀匹配
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH%bin}
                    /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter/pattern/string}
              模式替换,pttern将被替换成string
              正常情况下pattern 只有第一个匹配的会陪替换成string
              如果表达式以#开头,如:#w,则必须匹配以w开头的
              如果表达式以%几位,如:t%,则必须匹配以t结尾的
              pattern支持通配符*,如:${PWD/*/s},则变量PWD的值全部被替换成s
              如果parameter是一个数组变量,则数组中的成员都会执行此操作,返回一个匹配结果数
                例如:
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${PATH/#\/usr/s}
                    s/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
                    root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

       ${parameter^pattern}
       ${parameter^^pattern}
       ${parameter,pattern}
       ${parameter,,pattern}
              大小写转换.
              ^ 操作将pattern的匹配结果转换成大写字母,第一个字符
              , 操作将pattern的匹配结果转换成小写字母,第一个字符
              ^^ 操作将pattern的匹配结果转换成大写字母
              ,, 操作将pattern的匹配寄过转换成小写字母
              
              如果parameter是一个数组变量,则数组中的每个成员将会与pattern做匹配
              通配符:
                * 在^^和,,操作中表示0个或多个字符,在^和,中表示一个或0个字符
                ? 与*相同
             例如:
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM,*} 
                xterm
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM^*} 
                Xterm
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM^^*} 
                XTERM
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# echo ${TERM,,*} 
                xterm
                root@iZuf6ilzd4iqvuj4dvuiwtZ:~# 

参考资料