Shell特殊變數:Shell $0, $#, $*, $@, $?, $$和命令列參數

來源:互聯網
上載者:User

標籤:

變數名只能包含數字、字母和底線,因為某些包含其他字元的變數有特殊含義,這樣的變數被稱為特殊變數。

例如,$ 表示當前Shell進程的ID,即pid,看下面的代碼:

  1. $echo $$

運行結果

29949

 

特殊變數列表
變數 含義
$0 當前指令碼的檔案名稱
$n 傳遞給指令碼或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。
$# 傳遞給指令碼或函數的參數個數。
$* 傳遞給指令碼或函數的所有參數。
[email protected] 傳遞給指令碼或函數的所有參數。被雙引號(" ")包含時,與 $* 稍有不同,下面將會講到。
$? 上個命令的退出狀態,或函數的傳回值。
$$ 當前Shell進程ID。對於 Shell 指令碼,就是這些指令碼所在的進程ID。
命令列參數

運行指令碼時傳遞給指令碼的參數稱為命令列參數。命令列參數用 $n 表示,例如,$1 表示第一個參數,$2 表示第二個參數,依次類推。

請看下面的指令碼:

  1. #!/bin/bash
  2. echo "File Name: $0"
  3. echo "First Parameter : $1"
  4. echo "First Parameter : $2"
  5. echo "Quoted Values: [email protected]"
  6. echo "Quoted Values: $*"
  7. echo "Total Number of Parameters : $#"

運行結果:

$./test.sh Zara AliFile Name : ./test.shFirst Parameter : ZaraSecond Parameter : AliQuoted Values: Zara AliQuoted Values: Zara AliTotal Number of Parameters : 2
$* 和 [email protected] 的區別

$* 和 [email protected] 都表示傳遞給函數或指令碼的所有參數,不被雙引號(" ")包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數。

但是當它們被雙引號(" ")包含時,"$*" 會將所有的參數作為一個整體,以"$1 $2 … $n"的形式輸出所有參數;"[email protected]" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數。

下面的例子可以清楚的看到 $* 和 [email protected] 的區別:

  1. #!/bin/bash
  2. echo "\$*=" $*
  3. echo "\"\$*\"=" "$*"
  4. echo "\$@=" [email protected]
  5. echo "\"\$@\"=" "[email protected]"
  6. echo "print each param from \$*"
  7. for var in $*
  8. do
  9. echo "$var"
  10. done
  11. echo "print each param from \$@"
  12. for var in [email protected]
  13. do
  14. echo "$var"
  15. done
  16. echo "print each param from \"\$*\""
  17. for var in "$*"
  18. do
  19. echo "$var"
  20. done
  21. echo "print each param from \"\$@\""
  22. for var in "[email protected]"
  23. do
  24. echo "$var"
  25. done

執行 ./test.sh "a" "b" "c" "d",看到下面的結果:

$*=  a b c d"$*"= a b c d[email protected]=  a b c d"[email protected]"= a b c dprint each param from $*abcdprint each param from [email protected]abcdprint each param from "$*"a b c dprint each param from "[email protected]"abcd
退出狀態

$? 可以擷取上一個命令的退出狀態。所謂退出狀態,就是上一個命令執行後的返回結果。

退出狀態是一個數字,一般情況下,大部分命令執行成功會返回 0,失敗返回 1。

不過,也有一些命令返回其他值,表示不同類型的錯誤。

下面例子中,命令成功執行:

$./test.sh Zara AliFile Name : ./test.shFirst Parameter : ZaraSecond Parameter : AliQuoted Values: Zara AliQuoted Values: Zara AliTotal Number of Parameters : 2$echo $?0$


$? 也可以表示函數的傳回值

 

 

 

 

 

1 shell變數基礎
shell變數是一種很“弱”的變數,預設情況下,一個變數儲存一個串,shell不關心這個串是什麼含義。所以若要進行數學運算,必須使用一些命令例如let、declare、expr、雙括弧等。shell變數可分為兩類:局部變數和環境變數。局部變數只在建立它們的shell中可用。而環境變數則可以在建立它們的shell及其派生出來的任意子進程中使用。有些變數是使用者建立的,其他的則是專用shell變數。變數名必須以字母或底線開頭。其餘的字元可以是字母、數字(0~9)或底線。任何其他的字元都標誌著變數名的終止。名字是大小寫敏感的。給變數賦值時,等號周圍不能有任何空白符。為了給變數賦空值,可以在等號後跟一個分行符號。用set命令可以查看所有的變數,unset var命令可以清除變數var,var相當於沒有定義過。readonly var可以把var變為唯讀變數,定義之後不能對var進行任何更改。對shell變數的引用方式很多,用這些方式可以方便的擷取shell變數的值,變數值的長度,變數的一個字串,變數被部分替換後的值等等。shell變數常見引用方式如下:

2 環境變數
環境變數的定義方法如下:
var=value
export var
shell在初始化的時候會在執行profile等初始化指令碼,指令碼中定義了一些環境變數,這些變數會在建立子進程時傳遞給子進程。
用env命令可以查看當前的環境變數。常用的系統內容變數如下:
_(底線) 上一條命令的最後一個參數
BASH 展開為調用bash執行個體時使用的全路徑名
CDPATH cd命令的搜尋路徑。它是以冒號分隔的目錄列表,shell通過它來搜尋cd命令指定的目標目錄。例如.:~:/usr
EDITOR 內建編輯器emacs、gmacs或vi的路徑名
ENV 每一個新的bash shell(包括指令碼)啟動時執行的環境檔案。通常賦予這個變數的檔案名稱是.bashrc。
EUID 展開為在shell啟動時被初始化的目前使用者的有效ID
GROUPS 目前使用者所屬的組
HISTFILE 指定儲存命令列曆史的檔案。預設值是~/.bash_history。如果被複位,互動式shell退出時將不儲存命令列曆史
HISTSIZE 記錄在命令列曆史檔案中的命令數。預設是500
HOME 主目錄。未指定目錄時,cd命令將轉向該目錄
IFS 內部欄位分隔符號,一般是空格符、定位字元和分行符號,用於由命令替換,迴圈結構中的表和讀取的輸入產生的詞的欄位劃分
LANG 用來為沒有以LC_開頭的變數明確選取的種類確定locale類
OLDPWD 前一個工作目錄
PATH 命令搜尋路徑。一個由冒號分隔的目錄列表,shell用它來搜尋命令,一個普通值為 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
PPID 父進程的進程ID
PS1 主提示符串,預設值是$
PS2 次提示符串,預設值是>
PS3 與select命令一起使用的選擇提示符串,預設值是#?
PS4 當開啟追蹤時使用的調試提示符串,預設值是+。追蹤可以用set –x開啟
PWD 當前工作目錄。由cd設定
RANDOM 每次引用該變數,就產生一個隨機整數。隨機數序列可以通過給RANDOM賦值來初始化。如果RANDOM被複位,即使隨後再設定,它也將失去特定的屬性
REPLY 當沒有給read提供參數時設定
SHELL 當調用shell時,它掃描環境變數以尋找該名字。shell給PATH、PS1、PS2、MAILCHECK和IFS設定預設值。HOME和MAIL由login(1)設定
SHELLOPTS 包含一列開啟的shell選項,比如braceexpand、hashall、monitor等
UID 展開為目前使用者的使用者ID,在shell啟動時初始化
3 數值變數
shell中預設把變數值當作字串,例如:
age=22
age=${age}+1
echo ${age}
輸出結果為22+1,而不是23,因為shell將其解釋為字串,而不是數學運算。
可以用let命令使其進行數學運算,例如:
let age=${age}+1
也可以用declare把變數定義為整型。例如:
declare -i age=22
這裡就用 -i 選項把age定義為整型的了。此後每次運算,都把age的右值識別為算術運算式或數字。
4 數組
在shell中可以使用數組,例如:
array[0]=0
array[1]=1
array[2]=2
則array就是一個數組,也可以這樣給數組初始化:
array=(0 1 2) // 元素之間以空格分隔
可以通過 ${array[$i]}來訪問array中某個元素,${array[*]} 的傳回值即數組的所有元素組成的串,${#array[*]} 的傳回值即數組的元素個數,${array[*]:0:2} 返回第一個和第二個元素組成的串。0表示開始的位置,2表示要返回的元素個數,開始位置可以為0-2(0減去2)之類的,表示從倒數第二個元素開始。
下面寫個稍微複雜點的例子:

1 #!/bin/bash2 for ((i=0; i<100; i++))3 do4 array[$i]=$i5 done6 for ((i=0; i<100; i++))7 do8 echo ${array[$i]}9 done

如果要使用二維數組甚至三維數組該怎麼實現呢,那就需要用eval命令來類比數組的功能了。
eval命令的作用是掃描命令兩次再執行,如果不使用eval,只掃描一次,然後執行。看個例子:
[email protected]:~$ name=Barry
[email protected]:~$ $name=hello
Barry=hello: command not found
為什麼第二句給Barry變數賦值會出錯呢?從報錯資訊可以發現shell並沒有識別這是個指派陳述式,而是把Barry=hello當作一個命令來執行,當然會報錯。為什麼不能識別這是指派陳述式呢?第一次掃描時,因為掃描到$符號,所以不能把這句當作指派陳述式,指派陳述式的左邊總是一個變數名,而不應該是$開頭的。所以第一次掃描僅僅識別了$name變數,並做了替換,而並沒有認識到指派陳述式。
如果使用eval $name=hello呢?
[email protected]:~$ name=Barry
[email protected]:~$ $name=hello
Barry=hello: command not found
[email protected]:~$ eval $name=hello
[email protected]:~$ echo $Barry
hello
可見使用了eval之後,對 $name=hello 第一次掃描替換了$name,沒有識別指派陳述式,第二次掃描識別是指派陳述式,然後執行。現在大約可以想到怎樣用eval實現二維數組了。
下面實現的二維數組每一行代表一個人的資訊記錄,包括姓名,年齡。

 1 for ((i=0; i<2; i++)) 2 do 3 for ((j=0; j<2; j++)) 4 do  5 read man$i$j 6 done 7 done 8 echo "next print:" 9 for ((i=0; i<2; i++))10 do11 for ((j=0; j<2; j++))12 do 13 eval echo -n "\$man$i$j:"14 done15 printf "\n"16 done

5 特殊變數
$0:當前指令碼的檔案名稱
$num:num為從1開始的數字,$1是第一個參數,$2是第二個參數,${10}是第十個參數
$#:傳入指令碼的參數的個數
$*:所有的位置參數(作為單個字串)
[email protected]:所有的位置參數(每個都作為獨立的字串)。
$?:當前shell進程中,上一個命令的傳回值,如果上一個命令成功執行則$?的值為0,否則為其他非零值,常用做if語句條件
$$:當前shell進程的pid
$!:後台啟動並執行最後一個進程的pid
$-:顯示shell使用的當前選項
$_:之前命令的最後一個參數

Shell特殊變數:Shell $0, $#, $*, [email protected], $?, $$和命令列參數

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.