# Shell中的變量
[TOC]
## Shell定義變量需要遵循的規則
Shell編程中,使用變量無需事先聲明,同時變量名的命名須遵循如下規則:
1. 首個字符必須為字母(a-z,A-Z),推薦統一使用大寫字母
2. 中間不能有空格,可以使用下劃線(_)
3. 不能使用標點符號
4. 不能使用bash里的關鍵字(可用help命令查看保留關鍵字)
## shell變量賦值
需要給變量賦值時,可以這么寫:
`變量名=值`
## unset取消本地的環境變量
`unset USER`
## 變量種類
### Shll中系統環境變量
shell在初始化的時候會在執行`/etc/profile`和`~/.bash_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啟動時初始化
### Shell中局部變量
局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啟動的程序不能訪問局部變量。
#### 普通字符串的定義
>
變量名=value
變量名='value'
變量名="value"
**例一:**
~~~
a=192.168.0.200
b='192.168.0.200'
c="192.168.0.200"
echo "a=$a"
echo "b=$b"
echo "c=${c}"
~~~
**例一運行結果:**
~~~
a=192.168.0.200
b=192.168.0.200
c=192.168.0.200
~~~
**例二:**
~~~
a=192.168.0.200
a=192.168.0.200-$a
b='192.168.0.200-$a'
c="192.168.0.200-$a"
echo "a=$a"
echo "b=$b"
echo "c=$c"
~~~
**例二運行結果:**
~~~
a=192.168.0.200-192.168.0.200
b=192.168.0.200-$a
c=192.168.0.200-192.168.0.200-192.168.0.200
~~~
> **提示:**
定義變量a的方式是直接定義變量內容,內容一般為簡單連續(無空格)的數字、字符串、路徑名等;
定義變量b的方式是**通過單引號定義變量**,特點是輸出變量時引號里是什么就輸出什么,即使**內容中有變量也會把變量名原樣輸出**,適合定義顯示純字符串;
定義變量c的方式是通過**雙引號定義變量**,特點是**輸出變量時引號內的變量會經過解析后輸出該變量內容**,而不是把引號中變量名原樣輸出,適合于字符串中附帶變量的內容的定義。
#### 腳本中局部變量定義
存在于腳本函數(function)中的變量稱為局部變量,要以local方式進行生命,使之只在本函數作用域內有效,防止變量在函數中的命名與變量外部程序中變量重名造成程序異常。
具體實例可以參考`/ect/init.d/functions`相關的定義方式。
### Shell中特殊變量
#### 位置變量
>
**$0:當前腳本的文件名**
**$n:n為從1開始的數字,$1是第一個參數,$2是第二個參數,${10}是第十個參數**
**$#:傳入腳本的參數的個數**
$*:所有的位置參數(作為單個字符串)
$@:所有的位置參數(每個都作為獨立的字符串)。
#### 進程狀態變量
>
**$?:當前shell進程中,上一個命令的返回值,如果上一個命令成功執行則$?的值為0,否則為其他非零值,常用做if語句條件**
$$:當前shell進程的pid
$!:后臺運行的最后一個進程的pid
$-:顯示shell使用的當前選項
$_:之前命令的最后一個參數
### bash內部變量
有些內部命令在目錄列表時是看不見的,他們有Shell本身提供,常見的內部命令:**echo**,**export**,**read**,**shift**,eval,exec,readonly,wait,exit和點(.)
#### **echo 變量名表**
將變量名表指定的變量顯示到標準輸出
#### **export 變量名=value**
Shell 可以用export把它的變量向下打入子Shell,從而讓子進程繼承父進程中的環境變量,但子Shell不能用export把他的變量向上帶入父Shell
#### **read 變量名表**
從標準輸入讀取字符串,傳給指定變量,可以在函數中用local變量名的方式申明局部變量。
#### **shift 語句**
shift 語句按如下方式重新命名所有的位置參數變量,即 $2成為$1,$3成為$2…在程序中每使用一次shift語句,都使得所有的位置一次向左移動一個位置,并使位置參數$#減1,直到減到0為止。
#### eval args
讀入參數args ,并將他們組合成一個新的命令,然后執行
#### exec 命令參數
當Shell執行到exec語句時,不會去創建新的子進程,而是轉去執行新的命令,當指定的命令執行完時,該進程(也就是當初的Shell)就終止了,所以shell程序中的exec后面的語句將不再被執行
#### readonly 變量名
從邊準輸入讀字符床,傳給指定變量