導(dǎo)讀
之前我們已經(jīng)依次講過(guò) zsh 下的五種變量(字符串、數(shù)組番捂、哈希表个唧、整數(shù)、浮點(diǎn)數(shù))的基本用法设预。但變量的使用方面徙歼,還有一些比較進(jìn)階的內(nèi)容,這對(duì)一些比較特別的場(chǎng)景很有幫助。
typeset 命令
typeset 命令用于對(duì)變量進(jìn)行詳細(xì)的設(shè)置魄梯。我們之前在哈希表那篇見(jiàn)過(guò)它桨螺。typeset -A 可以用來(lái)定義哈希表。
% typeset -A hashmap=(aa bb cc dd)
但我們后續(xù)都使用 local酿秸,因?yàn)?local 的功能和 hashmap 是一樣的(除了不能用 -f 和 -g灭翔,這兩個(gè)選項(xiàng)不常用),并且更短更容易輸入辣苏。這里提到 typeset 命令肝箱,因?yàn)檫@個(gè)名稱很好地反映了它的功能。但知道了這個(gè)后稀蟋,我們可以繼續(xù)使用 local 命令煌张,畢竟它們是一樣的。
typeset 命令有很多選項(xiàng)退客,可以作用在變量上骏融,起到各種各樣的效果。
強(qiáng)制字符串內(nèi)容為小寫(xiě)或者大寫(xiě)
# 強(qiáng)制字符串內(nèi)容為小寫(xiě)
% local -l str=abcABC && echo $str
abcabc
# 強(qiáng)制字符串內(nèi)容為大寫(xiě)
% local -u str=abcABC && echo $str
ABCABC
設(shè)置變量為環(huán)境變量
% local -x str=abc
# 通常使用 export萌狂,功能一樣
% export str=abc
環(huán)境變量可以被子進(jìn)程讀取档玻。
設(shè)置變量為只讀變量
% local -r str1=abc
# 通常使用 readonly,功能一樣
% readonly str2=abc
% str1=bcd
zsh: read-only variable: str1
% str2=bcd
zsh: read-only variable: str2
設(shè)置數(shù)組不包含重復(fù)元素
% local -U array=(aa bb aa cc) && echo $array
aa bb cc
設(shè)置整數(shù)的位數(shù)
# 如果位數(shù)不夠茫藏,輸出內(nèi)容會(huì)用 0 補(bǔ)全
% local -Z 3 i=5 && echo $i
005
# 如果超出范圍會(huì)被截?cái)?% local -Z 3 i=1234 && echo $i
234
進(jìn)制轉(zhuǎn)換
設(shè)置整數(shù)為其他進(jìn)制顯示:
% local -i 16 i=255
% echo $i
16#FF
可以設(shè)置 2 到 36 之間任意進(jìn)制误趴。設(shè)置幾進(jìn)制顯示,并不影響計(jì)算刷允,只是顯示格式不同。
用 [#n] num 也可以顯示十進(jìn)制數(shù)為 n 進(jìn)制:
% echo $(([#16] 255))
16#FF
可以用 n#num 來(lái)顯示 n 進(jìn)制整數(shù)為十進(jìn)制:
% echo $((16#ff))
255
我們可以定義一系列函數(shù)來(lái)快捷地轉(zhuǎn)換進(jìn)制碧囊,不需要使用 bc 等外部命令:
0x() {
echo $((16#$1))
}
0o() {
echo $((8#$1))
}
0b() {
echo $((2#$1))
}
p16() {
echo $(([#16] $1))
}
p8() {
echo $(([#8] $1))
}
p2() {
echo $(([#2] $1))
}
# 其他進(jìn)制轉(zhuǎn)十進(jìn)制
% 0x ff
255
% 0b 1101
13
# 十進(jìn)制轉(zhuǎn)其他進(jìn)制
% p16 1234
16#4D2
同時(shí)對(duì)多個(gè)變量賦相同的值
% local {i,j,k}=123
% echo $i $j $k
123 123 123
綁定字符串和數(shù)組
% local -T DIR dir
% dir=(/a /b/c /b/d /e/f)
% echo $DIR
/a:/b/c:/b/d:/e/f
# 刪除 dir 后树灶,DIR 也會(huì)被刪除(反之亦然)
% unset dir
% echo $+DIR
0
Linux 下經(jīng)常需要處理帶分隔符冒號(hào)的字符串(比如 $PATH)。如果只修改其中某一個(gè)字段糯而,比較麻煩天通。local -T 可以把字符串綁定到數(shù)組上,這樣直接修改數(shù)組熄驼,字符串內(nèi)容也會(huì)同步變化(反之亦然)像寒。其實(shí)在 zsh 中,$PATH 字符串就是和 $path 數(shù)組綁定的瓜贾,可以直接通過(guò)修改 $path 來(lái)達(dá)到修改 $PATH 的目的诺祸,這在某些場(chǎng)景會(huì)方便很多。
顯示變量的定義方式
% array=(aa bb cc)
% local -p array
typeset -a array=(aa bb cc)
% array+=(dd)
% local -p array
typeset -a array=(aa bb cc dd)
什么地方該加雙引號(hào)
用過(guò) bash 的讀者大概會(huì)對(duì)里邊的雙引號(hào)印象比較深刻祭芦,很多地方不加雙引號(hào)都會(huì)出錯(cuò)筷笨,為了避免出錯(cuò),很多人每個(gè)變量左右都加上雙引號(hào),麻煩不說(shuō)胃夏,代碼看起來(lái)也比較亂轴或。
其實(shí) zsh 中已經(jīng)沒(méi)有那些問(wèn)題了,變量?jī)蛇厽o(wú)需加雙引號(hào)仰禀,不會(huì)出現(xiàn)莫名其妙的錯(cuò)誤照雁。但有些地方還是需要加雙引號(hào)的。
需要加雙引號(hào)的場(chǎng)景:
- 像這樣的包含字符或者特殊符號(hào)的字符串
"aa bb \t \n *"
出現(xiàn)在代碼中時(shí)答恶,兩邊要加雙引號(hào)饺蚊,這個(gè)基本不需要說(shuō)明。 - 在用
$()
調(diào)用命令時(shí)亥宿,如果希望結(jié)果按一個(gè)字符串處理卸勺,需要加上雙引號(hào),"$()"
烫扼,不然的話曙求,如果命令結(jié)果中有空格,$()
會(huì)被展開(kāi)成多個(gè)字符串映企。 - 如果想將數(shù)組當(dāng)單個(gè)字符串處理悟狱,需要加雙引號(hào),
array=(a b); print -l "$array"
堰氓。 - 其他的原本不是單個(gè)字符串的東西挤渐,需要轉(zhuǎn)成單個(gè)字符串的場(chǎng)景,要加雙引號(hào)双絮。
其余情況通常都不需要加雙引號(hào)浴麻,典型的情況:
- 任何情況下,字符串變量的兩邊都不需要加雙引號(hào)囤攀,無(wú)論里邊的內(nèi)容多么特殊软免,或者變量存不存在,都沒(méi)有關(guān)系焚挠,如
$str
膏萧。 - 如果不轉(zhuǎn)換類型(比如數(shù)組轉(zhuǎn)成字符串),任何變量的兩邊都不需要加雙引號(hào)蝌衔。
-
$1
$2
$*
這些參數(shù)(其實(shí)它們也都是單個(gè)字符串)榛泛,都不需要加雙引號(hào),無(wú)論內(nèi)容是什么噩斟,或者參數(shù)是否存在曹锨。
以上的 7 種情況幾乎覆蓋了所有場(chǎng)景,如果有沒(méi)覆蓋到的剃允,試一下即可(讓里邊的內(nèi)容包含空格艘希、換行和其他特殊字符等等硼身,看看結(jié)果是否符合預(yù)期)。
總結(jié)
本文簡(jiǎn)單介紹了一些比較使用的 typeset(或者 local)命令的用法覆享,typeset 命令還有很多其他參數(shù)佳遂,但一般很少用,以后我也會(huì)繼續(xù)更新撒顿。
參考
http://www.bash2zsh.com/zsh_refcard/refcard.pdf
http://www.linux-mag.com/id/1079/
更新歷史
20170831:新增“什么地方該加雙引號(hào)”
本文不再更新丑罪,全系列文章在此更新維護(hù):github.com/goreliu/zshguide
付費(fèi)解決 Windows、Linux凤壁、Shell吩屹、C、C++拧抖、AHK煤搜、Python、JavaScript唧席、Lua 等領(lǐng)域相關(guān)問(wèn)題擦盾,靈活定價(jià),歡迎咨詢淌哟,微信 ly50247迹卢。