Linux Shell程式設計(4)——shell特殊字元(上)

尹成發表於2014-09-30
在指令碼或其他別的地方出現的特殊字元


#
註釋. 以一個#開頭的行 (#!是例外) 是註釋行.


# 這是一行註釋.


註釋也可以出現在一個命令語句的後面。


echo "A comment will follow." # 這裡可以新增註釋.
#                            ^ 注意在#前面可以有空白符 #


註釋行前面也可以有空白字元.


 #注意這個註釋行的開頭是一個TAB鍵.



在同一行中,命令不會跟在一個註釋的後面。因為這種情況下沒有辦法分辨註釋的結尾,命令只能放在同一行的行首。用另外的一個新行開始下一個註釋。



當然了,在echo命令給出的一個轉義的#字元並不會開始一個註釋。同樣地,出現在一些引數代換結構和在數值常量表示式中的#字元也同樣不會開始一個註釋。
echo "The # here does not begin a comment."
echo 'The # here does not begin a comment.'
echo The \# here does not begin a comment.
echo The # here begins a comment.


echo ${PATH#*:}       # 前面的#是引數代換,不是註釋.
echo $(( 2#101011 ))  # 基本轉換,不是註釋.


# 多謝, S.C.
標準的引用和轉義 符("'\)可以轉義#。


當然,模式匹配操作也可以使用#,而不必把它當做註釋的開始。


;
命令分割符[分號]. 分割符允許在同一行裡有兩個或更多的命令.


echo hello; echo there




if [ -x "$filename" ]; then    # 注意:"if" and "then"需要分隔符
                               # 思考一下這是為什麼?
  echo "File $filename exists."; cp $filename $filename.bak
else
  echo "File $filename not found."; touch $filename
fi; echo "File test complete."


注意”;”有時需要轉義.


;;
case語句分支的結束符[雙分號].
case "$variable" in
abc)  echo "\$variable = abc" ;;
xyz)  echo "\$variable = xyz" ;;
esac


.


"點"命令[圓點]. 等同於source (參考例子 11-20).這是一個bash的內建命令.


.
"點", 作為一個檔名的組成部分.當點(.)以一個檔名為字首時,起作用使該檔案變成了隱藏檔案。這種隱藏檔案ls一般是不會顯示出來的。[譯者注:除非你加了選項-a]
 bash$ touch .hidden-file
   


作為目錄名時,單個點(.)表示當前目錄,兩個點(..)表示上一級目錄(譯者注:或稱為父目錄)。


 bash$ pwd
 /home/bozo/projects
 
 bash$ cd .
 bash$ pwd
 /home/bozo/projects
 
 bash$ cd ..
 bash$ pwd
 /home/bozo/
         


單點(.)檔名常常被當作檔案移動命令的目的路徑.


 bash$ cp /home/bozo/current_work/junk/* .
         


.
點(.)字元匹配.作為正規表示式的一部分,匹配字元時,單點(.)表示匹配任意一個字元。


"
部分引用[雙引號]. "STRING"的引用會使STRING裡的特殊字元能夠被解釋。請參考第五章.


'
完全引用[單引號]. 'STRING'能引用STRING裡的所有字元(包括特殊字元也會被原樣引用). 這是一個比使用雙引號(“)更強的引用。 參考第5章.


,
逗號操作符[逗號]. 逗號操作符用於連線一連串的數學表示式。這一串的數學表示式每一個都被求值,但只有最後一個被返回。(譯者注:換句話說,就是整個表示式的值取決於最後一個表示式的值。)
   1 let "t2 = ((a = 9, 15 / 3))"  # Set "a = 9" and "t2 = 15 / 3"


\
轉義符[後斜槓].用於單個字元的引用機制。


\X "轉義"字元為X.它有"引用"X的作用,也等同於直接在單引號裡的'X'.\符也可以用於引用雙引號(")和單引號('),這時雙引號和單引號就表示普通的字元,而不是表示引用了。


參考第五章對轉義字元的更深入的解釋。


/
檔案路徑的分隔符[前斜槓]. 分隔一個檔案路徑的各個部分。(就像/home/bozo/projects/Makefile).


它也是算術操作符中的除法.


`
命令替換.`command` 結構使字元(`)[譯者注:這個字元不是單引號,而是在標準美國鍵盤上的ESC鍵下面,在字元1左邊,在TAB鍵上面的那個鍵,要特別留心]引住的命令(command)執行結果能賦值給一個變數。它也被稱為後引號(backquotes)或是斜引號(backticks).


:


空命令[冒號]. 這個命令意思是空操作(即什麼操作也不做). 它一般被認為是和shell的內建命令true是一樣的。冒號":" 命令是Bash自身內建的, and its它的退出狀態碼是真(即0)。[譯者注:shell中真用數字0表示].


:
echo $?   # 0


死迴圈可以這麼寫:
while :
do
   operation-1
   operation-2
   ...
   operation-n
done


# 等同於:
#    while true
#    do
#      ...
#    done


在if/then的測試結構中用作佔位符:


if condition
then :   # 什麼也不做的分支
else
   take-some-action
fi


在必須要有兩元操作的地方作為一個分隔符, 參考例子 8-2和預設引數.


: ${username=`whoami`}
# ${username=`whoami`}   如果沒有開頭的:,將會出錯
#                        除非"username"是一個外部命令或是內建命令...


在here document中的一個命令作為一個分隔符.


在引數替換中為字串變數賦值
: ${HOSTNAME?} ${USER?} ${MAIL?}
#  如果列出的一個或多個基本的環境變數沒有設定,
#+ 將列印出錯資訊。


變數擴充套件/子串代換.


和重定向操作符(>)連用, 可以把一個檔案的長度截短為零,檔案的許可權不變。如果檔案不存在,則會建立一個新檔案。
: > data.xxx   # 檔案"data.xxx"現在長度為0了      


# 作用相同於:cat /dev/null >data.xxx(譯者注:echo >data.xxx也可以)
# 但是,用NULL(:)操作符不會產生一個新的程式,因為NULL操作符是內建的。
請參考例子 12-14.


和新增重定向操作符(>>)連用(: >> target_file).如果目標檔案存在則什麼也沒有發生,如果目標檔案不存在,則建立它。



這隻能應用在普通檔案中,不能用在管道,符號連結和其他的特殊檔案。


雖然這是不被推薦的,但是NULL操作符(:)也可以用於開始註釋一行。使用#來註釋一行將會使Bash不會檢查這行後面的語法是否有錯,因此#註釋幾乎可以出現任何的東西。但是,對於用NULL操作符(:)註釋的行則不是這樣。


下面一個會產生錯誤的註釋。
   1 : This is a comment that generates an error, ( if [ $x -eq 3] ).


字元”:”也用於域分割符。比如說在/etc/passwd和環境變數$PATH裡.
 bash$ echo $PATH
 /usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games


!


取反一個測試結果或退出狀態[感嘆號]. 取反操作符(!)取反一個命令的退出狀態。它也取反一個測試操作。例如,它能改相等符( = )為不等符( != ).取反操作符(!)是一個Bash的關鍵字.


在不同的環境裡,感嘆號也可以出現在間接變數引用.


還有一種環境裡,在命令列中,感嘆號(!)呼叫屬於歷史命令機制的呼叫(詳細請看附錄 J).值得一提的是,在一個指令碼里,命令歷史機制是被禁止的。


*
萬用字元[星號].星號(*)字元在用於匹配檔名擴充套件的一個萬用字元.它自動匹配給定的目錄下的每一個檔案。


 bash$ echo *
 abs-book.sgml add-drive.sh agram.sh alias.sh
       


星號(*)也用於正規表示式中匹配任意數字字元。.


*
算術操作符. 在計算時,星號(*)表示乘法運算子。兩個星號(**)表示求冪運算子。


?
測試操作符.在一些表示式中,問號(?)表示一個條件測試.


在雙括號結構裡,問號(?)表示C風格的三元操作符.請參考例子 9-30.


在引數替換表示式裡,問號(?)測試一個變數是否被設定了值.


?
萬用字元. 字元?被用於檔名擴充套件特性的檔名錶達式的單字元匹配,同時也在擴充套件正規表示式中匹配任意一個字元.


$
變數替換 (引用一個變數的內容).
var1=5
var2=23skidoo


echo $var1     # 5
echo $var2     # 23skidoo


一個變數名前面加一個$字元字首表示引用該變數的內容。


$
行的結尾. 在正規表示式裡,一個$字元表示匹配一行的結尾。


 
${}
引數替換.


$*, $@
位置引數.


$?
儲存退出碼值的變數. 變數$?儲存了一個命令,一個函式,或一個指令碼的退出狀態碼的值。


$$
程式ID變數. 變數$$儲存了指令碼執行時的程式ID值。


()
命令組.
   1 (a=hello; echo $a)



一組由圓括號括起來的命令是新開一個子shell來執行的.


因為是在子shell裡執行,在圓括號裡的變數不能被指令碼的其他部分訪問。因為父程式(即指令碼程式)不能存取子程式(即子shell)建立的變數。
a=123
( a=321; )      


echo "a = $a"   # a = 123
# 在圓括號裡的變數"a"實際上是一個區域性變數,作用局域只是在圓括號內用於陣列始初化


陣列初始化.
 Array=(element1 element2 element3)


{xxx,yyy,zzz,...}
擴充套件支援.
cat {file1,file2,file3} > combined_file
# 連線file1,file2,和file3的內容並寫到檔案combined_file裡去.




cp file22.{txt,backup}
# 拷貝"file22.txt"內容為"file22.backup"


一個命令可以在檔名擴充套件中從逗號分隔的各模式來擴充套件引數列表。 [1] 檔名將會依照列表中逗號分隔開的模式匹配擴充套件。

相關文章