Shell 編程:Bash空格的那點事
先了解下bash中什么時候該用空格,什么時候不該用。
1. 等號賦值兩邊不能有空格
2. 命令與選項之間需要空格
3. 管道兩邊空格可有可無
我們來看看常見的問題
1. 賦值時等號兩邊或者只有左邊多了空格
igi@gentoo ~ $ var1 = test
bash: var1: command not found
igi@gentoo ~ $ echo ${var1:?error}
bash: var1: error
igi@gentoo ~ $ echo ${var1?error}
bash: var1: error
igi@gentoo ~ $ var2 =test
bash: var2: command not found
igi@gentoo ~ $ echo ${var2:?error}
bash: var2: error
igi@gentoo ~ $ echo ${var2?error}
bash: var2: error
這里我用了bash的變量擴展,${var1:?error}當var1為unset或null(未定義或空)時, 報指定錯誤; ${var1?error}當var1為unset時,報指定錯誤 。從執(zhí)行結(jié)果來看,如果等號左邊有空格,則變量名當成命令執(zhí)行,結(jié)果報command not found,變量沒有被賦值
2. 賦值時等號左邊沒有空格,右邊有空格(這種情況有點特別,你會發(fā)現(xiàn)兩種情況)
igi@gentoo ~ $ var= test igi@gentoo ~ $ var= nocmd bash: nocmd: command not found
同樣是等號右邊有空格,第一條命令沒報錯,而第二條報錯了。
這是因為shell中有這么一種執(zhí)行命令的方式: var=string command
命令command將得到變量var的值(至于在命令執(zhí)行后,變量var的值是否保留下來,bash4中沒有保留,但我在dash中發(fā)現(xiàn)時保留下來的,不 同的shell對這個的處理不同), 由于test是個命令,而nocmd不是,所以報了command not found.
igi@gentoo ~ $ var=newtest eval echo \$var newtest igi@gentoo ~ $ echo $var
注意: 這里我使用了eval, 是想避免在第一次解析時$var被替換成空字符串, 不然就會出現(xiàn)下面的情況(下面是錯誤的測試方法,在echo還沒執(zhí)行時,$var已經(jīng)被替換成空字符串)
igi@gentoo ~ $ var=newtest echo $var
igi@gentoo ~ $ echo $var
到這里,相信大家都明白了吧, 對于等號賦值,左右兩邊不可以有空格,雖然右邊有空格不一定報錯,但那絕對不是你想要的結(jié)果。
3. 命令和選項之間必須有空格
這個似乎大家都明白,為何我還這么羅嗦呢?說到這里,不得不提一下一個非常特別的命令: [ 命令(你沒看錯,是[ ), 也就是test命令(當然bash中,這是個內(nèi)置命令,但在這里不影響
我們的理解)?;蛟S你會覺得[命令眼熟,沒錯,我保證你見過它,來看看下面的例子
igi@gentoo ~ $ if [ "abc" = "abc" ]; then echo ‘they are the same'; fi they are the same igi@gentoo ~ $ type -a [ [ is a shell builtin [ is /usr/bin/[
想起來了吧?[命令經(jīng)常用到if判斷中,當然也有人喜歡這么寫
igi@gentoo ~ $ [ "abc" = "cba" ] || echo ‘they are not the same' they are not the same igi@gentoo ~ $ type -a [ [ is a shell builtin [ is /usr/bin/[
[ 命令正名叫test命令,它們兩者幾乎一樣,為什么不是完全一樣?來看看這個
igi@gentoo ~ $ [ "abc" = "cba" bash: [: missing `]‘ igi@gentoo ~ $ [ "abc" = "cba" ] igi@gentoo ~ $ test "abc" = "cba" ] bash: test: too many arguments igi@gentoo ~ $ test "abc" = "cba"
清晰了吧,用[命令時,你必須給它個尾巴], 用test命令時,就不能加個尾巴。尾巴]是[最后一個參數(shù),不可缺少的參數(shù), 代表[命令的結(jié)束
扯了這么多,那到底這個和空格有毛關(guān)系?說這些,是先讓大家明白: [在shell中是個命令,它左右必須有空格!]是[的最后不可缺少的參數(shù),它兩邊也需要空格(雖然有些命令的參數(shù)能連一起,例如ps, 但[命令不行,它的參數(shù)之間必須有空格)。讓我們看看關(guān)于[常見的錯誤
a. if 與 [ 之間缺少空格
igi@gentoo ~ $ if[ "$HOME" = "/home/igi"];then echo 'equal'; fi bash: syntax error near unexpected token `then' igi@gentoo ~ $ if[ "$HOME" = "/home/igi" ];then echo 'equal'; fi bash: syntax error near unexpected token `then' igi@gentoo ~ $ if["$HOME" = "/home/igi"];then echo 'equal'; fi bash: syntax error near unexpected token `then' igi@gentoo ~ $ if["$HOME" = "/home/igi" ];then echo 'equal'; fi bash: syntax error near unexpected token `then'
語法分析錯誤,很明顯,if[ 對于bash來說,不知道是什么鬼東西
b. [與后面的參數(shù)之間缺少空格
igi@gentoo ~ $ if ["$HOME" = "/home/igi" ];then echo 'equal'; fi bash: [/home/igi: No such file or directory igi@gentoo ~ $ if ["$HOME" = "/home/igi"];then echo 'equal'; fi bash: [/home/igi: No such file or directory
["$HOME" 對于bash來說,也不知道是什么鬼東西
c. [ ] 之間的參數(shù)之間缺少空格
igi@gentoo ~ $ if [ "abc"="abc" ]; then echo 'equal'; fi equal igi@gentoo ~ $ if [ "abc"="cba" ]; then echo 'equal'; fi equal
第一條命令似乎是對的(實際上是正巧而已),看看第二條命令"abc" 和 "cba"明顯不同,但卻判斷為相同。這是因為參數(shù)之間缺少了空格,被[命令認為內(nèi)部是個值而已。看看下面的命令,你就會釋然
igi@gentoo ~ $ if [ 0 ]; then echo 'equal'; fi equal igi@gentoo ~ $ if [ "1" ]; then echo 'equal'; fi equal igi@gentoo ~ $ if [ "" ]; then echo 'equal'; fi igi@gentoo ~ $ if [ ]; then echo 'equal'; fi
在[ ] 內(nèi)部,如果只有一個值(那些因為缺少了空格而連一起的也算),不是空字符串就為真。所以在[ ] 之間的參數(shù),也要兩邊有空格,而不能堆一起
d. 參數(shù)和尾巴]之間缺少空格
這個就不羅嗦了,尾巴]也是[命令的參數(shù),如同上面所講,參數(shù)之間必須有空格
扯了這么多[命令與空格的事,但有些時候,缺了空格卻能正確運行, 當然這只是你好運, 一起來看看
igi@gentoo ~ $ var=' abc' igi@gentoo ~ $ if [$var = "abc" ];then echo 'equal'; fi equal igi@gentoo ~ $ if ["$var" = "abc" ];then echo 'equal'; fi bash: [ abc: command not found
之前Bash引號那點事提到過,雙引號包圍起來的是一個整體,而沒雙引號的時候,字符串前后的空格或制表符都被切開。如果恰巧你遇到了或者你故意要丟棄字符串前后的空格或制表符,那也不是不可能, 但非常不建議你這么寫,你的代碼將是非常脆弱的。
或者你該加的空格都加了,但還是報錯,這也可能和缺少雙引號有關(guān)。這樣的情況很普遍,最后再看看
igi@gentoo ~ $ var='' igi@gentoo ~ $ if [ "$var" = "abc" ];then echo 'equal'; fi igi@gentoo ~ $ if [ $var = "abc" ];then echo 'equal'; fi bash: [: =: unary operator expected igi@gentoo ~ $ dvar='a b c' igi@gentoo ~ $ if [ $dvar = "a b c" ];then echo 'equal'; fi bash: [: too many arguments igi@gentoo ~ $ if [ "$dvar" = "a b c" ];then echo 'equal'; fi equal
我再羅嗦一次,不要輕易省略雙引號。很清楚了吧?如果你還不明白,
請讀讀Bash引號那點事
最后,對于管道兩邊可有可無的空格,就不扯淡了,因為沒遇到有人對此有疑惑.
- Linux命令行和shell腳本編程寶典 Richard Blum
- shell腳本編程之for語句、if語句使用介紹
- Linux shell腳本編程if語句的使用方法(條件判斷)
- 5個Shell腳本編程入門練習例子
- Shell腳本編程中常用的數(shù)學運算實例
- shell 編程中空格的使用方法
- shell腳本編程實現(xiàn)9*9乘法表
- Linux Shell 腳本編程入門教程
- Shell腳本編程之判斷語句
- shell腳本編程之循環(huán)語句
- Shell編程中while與for的區(qū)別及用法詳解
- Linux下Shell編程快捷鍵大全(日常整理)
- 詳解Shell編程之變量數(shù)值計算(一)
- 詳解Shell編程之if語句實戰(zhàn)(小結(jié))
- Shell編程之case語句實戰(zhàn)(小結(jié))
- 對Linux下shell編程之for循環(huán)的實例講解
- Shell腳本編程30分鐘入門(小結(jié))
- shell編程入門之變量,字符串,數(shù)組,函數(shù)使用方法總結(jié)
相關(guān)文章
linux多線程編程詳解教程(線程通過信號量實現(xiàn)通信代碼)
這篇文章主要介紹了linux多線程編程詳解教程,提供線程通過信號量實現(xiàn)通信的代碼,大家參考使用吧2013-12-12

