我的目标是了解“变量属性”的一般概念希望它能帮助我理解Bash 中声明了什么。
什么是变量属性?为什么有人想要给变量赋予属性?为什么在使用变量时仅仅创建变量并在执行中扩展它们还不够“足够”?
答案1
通常,变量是存储值的地方。您为变量 ( ) 赋值var="some value"
,然后您可以通过变量扩展调用该值(写作"$var"
相当于写作"some value"
)。
当您为变量赋值时,或者在 shell 访问变量的其他情况下,可以使变量执行一些特殊操作。变量的属性是 shell 存储在变量名称和值旁边的注释,它告诉 shell 应用此特殊行为。
一个例子
declare -i x
告诉 shellx
必须只包含整数值。通常,当您为变量赋值时,shell 会获取等号右侧展开后得到的字符串,并将其存储为变量的值。但是,如果变量具有整数属性,则 shell 会将该字符串解析为算术表达式,并存储对该表达式求值的结果。例如:
$ x=2+2; echo $x
2+2
$ declare -i x; x=2+2; echo $x
4
$ declare -i x; x=2+hello; echo $x
2
$ declare -i x; x=2+
bash: 2+: syntax error: operand expected (error token is "+")
(第三行x=2+hello
设置x
为 2,因为hello
它是一个未定义的变量名,未设置的变量默认被默认解释为 0。)
更多示例
declare -l var
声明var
必须仅包含小写字母。当 shell 存储变量的值时,它会将所有大写字母转换为小写字母。declare -u var
进行另一个方向的转换。declare -r var
设为var
只读,这也是赋值的一种特殊行为:它会导致每个后续赋值var
失败。declare -x var
导致var
被输出到环境中。对于此属性,当 bash 运行外部命令时,会发生特殊行为:外部命令看到的环境包含 shell 运行外部命令时 shell 导出的变量。
答案2
从help declare
:
Options which set attributes:
-a to make NAMEs indexed arrays (if supported)
-A to make NAMEs associative arrays (if supported)
-i to make NAMEs have the `integer' attribute
-l to convert the value of each NAME to lower case on assignment
-n make NAME a reference to the variable named by its value
-r to make NAMEs readonly
-t to make NAMEs have the `trace' attribute
-u to convert the value of each NAME to upper case on assignment
-x to make NAMEs export
注意:declare
也可用于函数。
这些属性中的每一个都有一种或多种用途:
-a
- 使 NAME 成为索引数组(如果支持)
这并不是完全必要的,因为将参数设置为数组会自动将其声明为索引数组。使用它可以使您的代码更加明显和可读。
-A
- 使名称关联数组(如果支持)
据我所知,这是完全必要的,因为尝试设置关联数组而不先声明它会导致索引数组。
$ assoc=([foo]=bar)
$ declare -p assoc
declare -a assoc=([0]="bar")
$ unset assoc
$ declare -A assoc
$ assoc=([foo]=bar)
$ declare -p assoc
declare -A assoc=([foo]="bar" )
-i
- 使名称具有“整数”属性
如果您想确保您的参数可以,则很有用仅有的保存整数。这还允许您对赋值执行算术扩展。
$ declare -i a
$ a=foo
$ echo $a
0
$ a=1+1
$ echo $a
2
-l
- 在分配时将每个 NAME 的值转换为小写
将确保您的参数值始终全部小写。这是一个非常酷的功能,我之前没有意识到并且将来可能会使用。它消除了复杂的参数扩展或使用单独的实用程序的需要,例如tr
$ declare -l foo=Bar
$ echo $foo
bar
-n
- 使 NAME 成为对其值命名的变量的引用
就像间接引用一样。这可以消除eval
许多脚本中的使用。
$ a=foo
$ declare -n b=a
$ echo $b
foo
-r
- 使名称只读
这是一个很好的功能。它对于您想要设置一次并确保不更改的 shell/环境变量特别有用
$ declare -r foo=bar
$ echo $foo
bar
$ foo=baz
-bash: foo: readonly variable
-t
- 使NAME具有“trace”属性
我对此不太确定。我认为它可能只适用于函数。
-u
- 在赋值时将每个 NAME 的值转换为大写
相似-l
但相反
$ declare -u foo=bAr
$ echo $foo
BAR
-x
- 导出姓名
只是将变量导出到环境的另一种方法。