变量

变量(variable)在编程语言中用来表示数据。它本身只是一个标记,指向数据在计算机内存中的一个或一组地址。变量通常出现在算术运算,数量操作及字符串解析中。变量名是其所指向值的一个占位符(placeholder)。引用变量值的过程我们称之为变量替换(variable substitution)。 Bash没有变量声明,尝试使用一个未定义的变量,Bash 不会自动报错,而是会将其视为空字符串(如果变量没有被明确设置或未设置值)。这意味着在大多数情况下,使用未定义的变量不会导致脚本终止,但可能会导致意外的结果或难以调试的问题。变量的定义语法规则:

name=value
# =两边不能有空格,如果value中含有空格要使用引号包裹

命名规则

  • 变量名只能包含字母(大小写均可)、数字和下划线(_)。
  • 变量名不能以数字开头。
  • 变量名区分大小写。例如,var1、VAR1 和 vAr1 是三个不同的变量。
  • 通常,建议使用小写字母和下划线来命名变量,以符合 Bash 和其他 Unix-like 系统的传统。

变量赋值

通常使用=对变量进行赋值,同时也存在使用let、for循环、read表达式赋值
注意: 不要混淆 =-eq,后者用来进行比较而非赋值;同时也要注意 = 根据使用场景既可作赋值操作符,也可作比较操作符。

变量的值中如果包含空格或者其他特殊字符需要使用引号包裹(单引号和双引号都可以),变量的值可以使用命令执行的结果进行赋值,具体查看摘自《Bash脚本进阶指南》示例:

#!/bin/bash
# 非引用形式变量

echo

# 什么时候变量是非引用形式,即变量名前没有 '$' 符号的呢?
# 当变量在被赋值而不是被引用时。

# 赋值
a=879
echo "The value of \"a\" is $a."

# 使用 'let' 进行赋值
let a=16+5
echo "The value of \"a\" is now $a."

echo

# 在 'for' 循环中赋值(隐式赋值)
echo -n "Values of \"a\" in the loop are: "
for a in 7 8 9 11
do
  echo -n "$a "
done

echo
echo

# 在 'read' 表达式中(另一种赋值形式)
echo -n "Enter \"a\" "
read a
echo "The value of \"a\" is now $a."

echo

exit 0
#!/bin/bash

a=23              # 简单形式
echo $a
b=$a
echo $b

# 来我们玩点炫的(命令替换)。

a=`echo Hello!`   # 将 'echo' 命令的结果赋值给 'a'
echo $a
#  注意在命令替换结构中包含感叹号(!)在命令行中使用将会失效,
#+ 因为它将会触发 Bash 的历史(history)机制。
#  在shell脚本内,Bash 的历史机制默认关闭。

a=`ls -l`         # 将 'ls -l' 命令的结果赋值给 'a'
echo $a           # 不带引号引用,将会移除所有的制表符与分行符
echo
echo "$a"         # 引号引用变量将会保留空白符
                  # 查看 "引用" 章节。

# 摘自 /etc/rc.d/rc.local
R=$(cat /etc/redhat-release)
arch=$(uname -m)
echo "$arch"

exit 0

变量使用

变量使用方式可以分为两种:一是直接使用,另一是在双引号中引用。在之前的例子中,使用的$variablename其实是${variablename}的简单形式。如果尝试访问一个未设置的变量,Bash会将其视为空字符串,除非启用了set -u选项,这时会报错。引用未设置的变量通常会得到一个空字符串,但可以使用${variable:-default}来提供默认值:

#!/bin/bash
a="Hello,      World"
# 感叹号和!"作用
# 在单引号中变量不会被替换,输出:$a
echo '$a'
# 连续多个空格会被移除,仅保留一个,输出:Hello, World!
echo $
# 连续多个空格会被保留,输出:Hello,      World!
echo "$a"

echo "$b" 输出:
echo "${b:-default}" 输出:default

变量类型

本节内容来源自《Bash脚本进阶指南》 不同于许多其他编程语言,Bash 并不区分变量的类型。本质上说,Bash 变量是字符串,但在某些情况下,Bash 允许对变量进行算术运算和比较。决定因素则是变量值是否只含有数字。

样例 整数还是字符串?

#!/bin/bash
# int-or-string.sh

a=2334                   # 整数。
let "a += 1"
echo "a = $a "           # a = 2335
echo                     # 依旧是整数。


b=${a/23/BB}             # 将 "23" 替换为 "BB"。
                         # $b 变成了字符串。
echo "b = $b"            # b = BB35
declare -i b             # 将其声明为整数并没有什么作用。
echo "b = $b"            # b = BB35

let "b += 1"             # BB35 + 1
echo "b = $b"            # b = 1
echo                     # Bash 认为字符串的"整数值"为0。

c=BB34
echo "c = $c"            # c = BB34
d=${c/BB/23}             # 将 "BB" 替换为 "23"。
                         # $d 变为了一个整数。
echo "d = $d"            # d = 2334
let "d += 1"             # 2334 + 1
echo "d = $d"            # d = 2335
echo


# 如果是空值会怎样呢?
e=''                     # ...也可以是 e="" 或 e=
echo "e = $e"            # e =
let "e += 1"             # 空值是否允许进行算术运算?
echo "e = $e"            # e = 1
echo                     # 空值变为了一个整数。

# 如果时未声明的变量呢?
echo "f = $f"            # f =
let "f += 1"             # 是否允许进行算术运算?
echo "f = $f"            # f = 1
echo                     # 未声明变量变为了一个整数。
#
# 然而……
let "f /= $undecl_var"   # 可以除以0么?
#   let: f /= : syntax error: operand expected (error token is " ")
# 语法错误!在这里 $undecl_var 并没有被设置为0!
#
# 但是,仍旧……
let "f /= 0"
#   let: f /= 0: division by 0 (error token is "0")
# 预期之中。


# 在执行算术运算时,Bash 通常将其空值的整数值设为0。
# 但是不要做这种事情!
# 因为这可能会导致一些意外的后果。


# 结论:上面的结果都表明 Bash 中的变量是弱类型的。

exit $?

弱类型变量有利有弊。它可以使编程更加灵活、更加容易(给与你足够的想象空间)。但它也同样的容易造成一些小错误,容易养成粗心大意的编程习惯。

环境变量

特殊变量