变量
变量是能储存计算结果或能表示值抽象概念. 变量可以通过变量名访问.
变量声明
声明变量一般使用下面方式:
- 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 只读变量
-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:~#
变量调用
在声明变量一个变量时变量名称要遵守下列规则:
不能以特殊字符 (除了_), 数字, 美元符($) 开头
变量名不能是纯数字
变量名可以是英文或数字或特殊字符 (_) 的组合
调用变量时在变量明前面以 $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:~#
参考资料
Linux 中 set,env,declare,export 显示 shell 变量的区别 https://www.cnblogs.com/wfwenchao/p/6139039.html
shell 编程(四): 变量
来源: http://www.bubuko.com/infodetail-2565086.html