我的目標是了解「變數屬性」的一般概念希望它能幫助我理解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
- 匯出姓名
只是將變數導出到環境的另一種方法。