天天看點

shell程式設計之轉義和引用

shell中有兩類字元,一類是普通字元,在Shell中除了本身的字面意思外沒有其他特殊意義,即普通純文字;另一類即元字元,是Shell的保留字元,在Shell中有着特殊的含義。

一、轉義

轉義是指使用轉義符引用單個字元,進而使其表達單純的字元的字面含義。Shell中的轉義符是反斜杠"\",使用轉義符的目的是使轉義符後面的字元單純地作為字元出現,而不解釋其特殊的含義。

#試圖列印"$Dollar"字元串的錯誤示範

[root@Cfhost-170820-UCNK ~]# echo $Dollar

#此處列印為空,因為Shell嘗試列印出變量Dollar的值,但是這個變量并沒有聲明,是以列印出空行

#使用轉義字元轉義$字元

[root@Cfhost-170820-UCNK ~]# echo \$Dollar

$Dollar

#更多例子

#列印乘号。如果不用轉義符轉義*号,則*号會作為一般的通配符使用,結果是将工作目錄中的所有目錄和檔案名替換它

[root@Cfhost-170820-UCNK ~]# echo 8 \* 8 =64

8 * 8 =64

[root@Cfhost-170820-UCNK ~]# echo john\'s cat

john's cat

在上面的示例中,指令的輸出将會是空字元。由于"$"符号是一個特殊字元,是以"$Dollar"被Shell嘗試解釋為"取出并列印Dollar變量的值“,如果恰巧你在系統中定義了這個變量并給予指派,那麼此處會列印出該變量的值,無論是哪種,都不是你原先想要的結果。這時就要使用"\"來轉義"$"字元,讓"$"失去其特殊含義,而隻作為一個符号出現。

二、引用

引用是指字元串用某種符号括起來,以防止特殊字元被解析為其他意思。比如說上一小節中的轉義符就是一種引用。Shell中一共有4種引用符,分别是雙引号、單引号、反引号和轉義符。其中雙引号又叫”部分引用"或“弱引用”,可以引用出除$符、反引号、轉義符之外的所有字元;單引号又叫“全引用”或“強引用",可以引用所有字元;反引号則會将反引号括起來的内容解釋為系統指令。

1.部分引用

部分引用是指雙引号括起來的引用。在這種引用的方式中,$符、反引号(`)、轉義符(\)這3種特殊字元依然會被解析為特殊意義。比如,在定義一個變量後,使用echo列印出變量的時候,将它們用雙引号括起來,如下所示:

#聲明變量VAR03,并用echo列印出來。第一次直接列印,第二次用引号括起來,從輸出内容看好像沒什麼差別

[root@Cfhost-170820-UCNK ~]# VAR03=100

[root@Cfhost-170820-UCNK ~]# echo $VAR03

100

[root@Cfhost-170820-UCNK ~]# echo "$VAR03"

#聲明變量VAR03,内容為字元串,ABC之間有多個空格

[root@Cfhost-170820-UCNK ~]# VAR04="A B C"

#直接列印變量時,輸出内容隻保留了每個字母間的一個空格

[root@Cfhost-170820-UCNK ~]# echo $VAR04

A B C

#使用引号括起來的輸出内容和變量定義時的内容完全一緻的

[root@Cfhost-170820-UCNK ~]# echo "$VAR04"

A B C

2.全引用

全引用是指用單引号括起來的引用。,單引号中的任何字元都隻當作是普通字元(除了單引号·本身,也就是說單引号中間無法再包含單引号,即便用轉義符轉義單引号也不行)。所有在單引号中間無法再包含單引号,即便用轉義符轉義單引号也不行)。所有在單引号中的字元都隻能代表其作為字元的字面意義

單引号和雙引号在很多時候是一樣的,隻是要記住,在雙引号中的$符、反引号、轉義符還是會被解析成其特殊含義,而在單引号中所有的字元都隻是字面意思。下面的例子中,使用雙引号括起的内容中,$PWD被解析成/root,而在單引号中隻是按照原樣輸出"$PWD“字元串。

3.指令替換

指令替換是指将指令的标準輸出作為值賦給某個變量。比如,在某個目錄中輸入ls指令檢視目前所有目錄中的檔案,但如何将輸出存入某個變量中呢?這就需要使用指令替換了,也就是Shell程式設計中使用最頻繁的功能。

Shell中有兩種方式可以完成指令替換,一種是反引号(`),一種是$(),使用方法如下:

運作系統指令date可以獲得目前的系統時間。在很多時候我們需要記錄腳本運作時間,是以隻是運作這個指令沒有什麼意義,必須将該指令的運作結果記錄并儲存到變量中,并持久化到檔案中,才能為後期分析提供有用的參考依據。

[root@Cfhost-170820-UCNK ~]# DATE_01=`date`

[root@Cfhost-170820-UCNK ~]# DATE_02=$(date)

[root@Cfhost-170820-UCNK ~]# echo $DATE_01

Tue Nov 28 19:48:47 MSK 2017

[root@Cfhost-170820-UCNK ~]# echo $DATE_02

Tue Nov 28 19:49:02 MSK 2017

如果被引用的指令輸出的内容包括多行,此時如果不通過引用的方式輸出變量,則輸出的内容中将會删除換行符,檔案名之間會使用系統預設的空來填充,即輸出的内容隻占一行。

[root@Cfhost-170820-UCNK ~]# LS=`ls -l`

[root@Cfhost-170820-UCNK ~]# echo $LS

total 64 -rw-r--r-- 1 root root 128 Nov 26 15:01 Awd.txt -rw-r--r-- 1 root root 77 Nov 26 16:33 bc.sh -rw-r--r-- 1 root root 39 Nov 26 16:32 cal.bc -rw-r--r-- 1 root root 50 Nov 26 16:10 Namespace01.sh -rw-r--r-- 1 root root 50 Nov 26 16:12 Namespace02.sh -rw-r--r-- 1 root root 192 Nov 26 16:17 Namespace03.c -rw-r--r-- 1 root root 137 Nov 26 16:14 Namespace03.sh -rw-r--r-- 1 root root 8

以上使用反引号的部分都可以使用$()進行替換,因為它們是等價的。但反引号畢竟和單引号看起來類似,有時候會對檢視代碼造成困難,而使用$()就相對清晰,能有效地避免這種混亂。但是有些情景是必須使用$()的:$()支援嵌套,而反引号不行。

補充說明:Shell中的運算符主要有比較運算符、字元串運算符、檔案操作運算符、邏輯運算符、算術運算符。

算術運算符,Java中和shell基本一緻

通常運算使用一個關鍵字 expr

使用該關鍵字注意:操作符和操作數之間必須以空格隔開,否則無法運算,打出的是字元串

4.特殊字元

通配符,常見的通配符有*、?和用[]括起來的字元序列。其中*代表任意長度的字元串。問号(?)可用于比對任一單個字元。方括号[]代表比對其中的任意一個字元.

引号,引号包括單引号和雙引号,單引号又稱“全引用”或“強引用”;雙引号又稱"部分引用“或弱引用",所有用雙引号括起來的出美元符、反斜杠、反引号依然保持其特殊用途外,其餘都作為普通字元處理;而所有用單引号括起的部分都作為普通字元處理,但是要注意單引号中間不能出現雙引号,否則Shell無法判斷到底哪裡是單引号的起止位置。

5.注釋符(通常用#,這個不用多說,注釋的目的在于增強代碼可讀性和有利于後期管理)

6.雜項

反引号用于指令替換,和$()的作用相同,表示傳回目前指令的執行結果并指派給變量。

位置參數:

$0:腳本本身

$1、$2...${10}:腳本的第一個參數、第二個參數到第十個參數

$#:變量總數

$*、$@:顯示所有參數

$?:前一個指令退出的傳回值

$!:最後一個背景程序的ID号

!:通常代表取反