4.1 变量替换

变量名是其所指向值的一个占位符(placeholder)。引用变量值的过程我们称之为变量替换(variable substitution)。

$

接下来我们仔细区分一下变量名与变量值。如果变量名是 variable1, 那么 $variable1 就是对变量值的引用。[^1]

1. bash$ variable1=23

4. bash$ echo variable1
5. variable1

7. bash$ echo $variable1
8. 23

变量仅仅在声明时、赋值时、被删除时(unset)、被导出时(export),算术运算中使用双括号结构((…))时或在代表信号时(signal,查看样例 32-5)才不需要有 $ 前缀。赋值可以是使用 =(比如 var1=27),可以是在 read 语句中,也可以是在循环的头部(for var2 in 1 2 3)。

在双引号""字符串中可以使用变量替换。我们称之为部分引用,有时候也称弱引用。而使用单引号''引用时,变量只会作为字符串显示,变量替换不会发生。我们称之为全引用,有时也称强引用。更多细节将在第五章讲解。

实际上, $variable 这种写法是 ${variable} 的简化形式。在某些特殊情况下,使用 $variable 写法会造成语法错误,使用完整形式会更好(查看章节 10.2)。

样例 4-1. 变量赋值与替换

1. #!/bin/bash
2. # ex9.sh

4. # 变量赋值与替换

6. a=375
7. hello=$a
8. #   ^ ^

10. #----------------------------------------------------
11. # 初始化变量时,赋值号 = 的两侧绝不允许有空格出现。
12. # 如果有空格会发生什么?

14. #   "VARIABLE =value"
15. #            ^
16. #% 脚本将会尝试运行带参数 "=value" 的 "VARIABLE " 命令。

18. #   "VARIABLE= value"
19. #             ^
20. #% 脚本将会尝试运行 "value" 命令,
21. #+ 同时设置环境变量 "VARIABLE" 为 ""。
22. #----------------------------------------------------

25. echo hello    # hello
26. # 没有引用变量,"hello" 只是一个字符串...

28. echo $hello   # 375
29. #    ^          这是变量引用。

31. echo ${hello} # 375
32. #               与上面的类似,变量引用。

34. # 字符串内引用变量
35. echo "$hello"    # 375
36. echo "${hello}"  # 375

38. echo

40. hello="A B  C   D"
41. echo $hello   # A B C D
42. echo "$hello" # A B  C   D
43. # 正如我们所见,echo $hello 与 echo "$hello" 的结果不同。
44. # ====================================
45. # 字符串内引用变量将会保留变量的空白符。
46. # ====================================

48. echo

50. echo '$hello'  # $hello
51. #    ^      ^
52. #  单引号会禁用掉(转义)变量引用,这导致 "$" 将以普通字符形式被解析。

54. # 注意单双引号字符串引用效果的不同。

56. hello=    # 将其设置为空值
57. echo "\$hello (null value) = $hello"      # $hello (null value) =
58. # 注意
59. # 将一个变量设置为空与删除(unset)它不同,尽管它们的表现形式相同。

61. # -----------------------------------------------

63. # 使用空白符分隔,可以在一行内对多个变量进行赋值。
64. # 但是这会降低程序的可读性,并且可能会导致部分程序不兼容的问题。

66. var1=21  var2=22  var3=$V3
67. echo
68. echo "var1=$var1   var2=$var2   var3=$var3"

70. # 在一些老版本的 shell 中这样写可能会有问题。

72. # -----------------------------------------------

74. echo; echo

76. numbers="one two three"
77. #           ^   ^
78. other_numbers="1 2 3"
79. #               ^ ^
80. # 如果变量中有空白符号,那么必须用引号进行引用。
81. # other_numbers=1 2 3                  # 出错
82. echo "numbers = $numbers"
83. echo "other_numbers = $other_numbers"  # other_numbers = 1 2 3
84. # 也可以转义空白符。
85. mixed_bag=2\ ---\ Whatever
86. #           ^    ^ 使用 \ 转义空格

88. echo "$mixed_bag"         # 2 --- Whatever

90. echo; echo

92. echo "uninitialized_variable = $uninitialized_variable"
93. # 未初始化的变量是空值(null表示不含有任何值)。
94. uninitialized_variable=   # 只声明而不初始化,等同于设为空值。
95. echo "uninitialized_variable = $uninitialized_variable" # 仍旧为空

97. uninitialized_variable=23       # 设置变量
98. unset uninitialized_variable    # 删除变量
99. echo "uninitialized_variable = $uninitialized_variable"
100. # uninitialized_variable =
101. # 变量值为空
102. echo

104. exit 0

notice 一个未被赋值或未初始化的变量拥有空值(null value)。注意:null值不等同于0。

1. if [ -z "$unassigned" ] 2. then 3. echo "\$unassigned is NULL." 4. fi # $unassigned is NULL.

在赋值前使用变量可能会导致错误。但在算术运算中使用未赋值变量是可行的。

1. echo "$uninitialized" # 空行 2. let "uninitialized += 5" # 加5 3. echo "$uninitialized" # 5 4. # 结论: 5. # 一个未初始化的变量不含值(null),但在算术运算中会被作为0处理。

也可参考样例 15-23。

[^1]: 实际上,变量名是被称作左值(lvalue),意思是出现在赋值表达式的左侧的值,比如 VARIABLE=23。变量值被称作右值(rvalue),意思是出现在赋值表达式右侧的值,比如 VAR2=$VARIABLE。 事实上,变量名只是一个引用,一枚指针,指向实际存储数据内存地址的指针。