shell變量簡介
變量是任何一種編程語言都必不可少的組成部分,變量用來存放各種數據。腳本語言在定義變量時通常不需要指明類型,直接賦值就可以,Shell 變量也遵循這個規則。
在 Bash shell 中,每一個變量的值都是字符串,無論你給變量賦值時有沒有使用引號,值都會以字符串的形式存儲。
這意味着,Bash shell 在默認情況下不會區分變量類型,即使你將整數和小數賦值給變量,它們也會被視為字符串,這一點和大部分的編程語言不同。
定義變量
Shell 支持以下三種定義變量的方式:
variable=value variable='value' variable="value"
variable 是變量名,value 是賦給變量的值。如果 value 不包含任何空白符(例如空格、Tab縮進等),那么可以不使用引號;如果 value 包含了空白符,那么就必須使用引號包圍起來。使用單引號和使用雙引號也是有區別的,稍后我們會詳細說明。
注意,賦值號的周圍不能有空格,這可能和你熟悉的大部分編程語言都不一樣。
Shell 變量的命名規范和大部分編程語言都一樣:
- 變量名由數字、字母、下划線組成;
- 必須以字母或者下划線開頭;
- 不能使用 Shell 里的關鍵字(通過 help 命令可以查看保留關鍵字)。
變量定義舉例:
url=http://www.baidu.com
time_15_age=18
real_name='ken'
_author="ken"
使用變量
使用一個定義過的變量,只要在變量名前面加美元符號$即可,如:
author="ken" echo $author echo ${author}
變量名外面的花括號{ }是可選的,加不加都行,加花括號是為了幫助解釋器識別變量的邊界,比如下面這種情況:
skill="Java" echo "I am good at ${skill}Script"
如果不給 skill 變量加花括號,寫成echo "I am good at $skillScript",解釋器就會把 $skillScript 當成一個變量(其值為空),代碼執行結果就不是我們期望的樣子了。
推薦給所有變量加上花括號{ },這是個良好的編程習慣。
系統變量
在命令行提示符直接執行 env、set 查看系統或環境變量。env 顯示用戶環境變量,set 顯示 Shell 預先定義好的變量以及用戶變量。可以通過 export 導出成用戶變量。一些寫 Shell 腳本時常用的系統變量:
$SHELL |
默認 Shell |
$HOME |
當前用戶家目錄 |
$IFS |
內部字段分隔符 |
$LANG |
默認語言 |
$PATH |
默認可執行程序路徑 |
$PWD |
當前目錄 |
$UID |
當前用戶 ID |
$USER |
當前用戶 |
$HISTSIZE |
歷史命令大小,可通過 HISTTIMEFORMAT 變量設置命令執行時間 |
$RANDOM |
隨機生成一個 0 至 32767 的整數 |
$HOSTNAME |
主機名 |
1.4.2 普通變量與臨時環境變量
普通變量定義:VAR=value
臨時環境變量定義:export VAR=value
變量引用:$VAR
下面看下他們之間區別:
Shell 進程的環境變量作用域是 Shell 進程,當 export 導入到系統變量時,則作用域是 Shell 進程及其 Shell 子進程,另開shell無效。
修改變量的值
已定義的變量,可以被重新賦值,如:
url="http://www.baidu.com" echo ${url} url="http://www.sina.com" echo ${url}
第二次對變量賦值時不能在變量名前加$,只有在使用變量時才能加$。
單引號和雙引號的區別
前面我們還留下一個疑問,定義變量時,變量的值可以由單引號' '包圍,也可以由雙引號" "包圍,它們到底有什么區別呢?不妨以下面的代碼為例來說明:
#!/bin/bash url="http://c.biancheng.net" website1='C語言中文網:${url}' website2="C語言中文網:${url}" echo $website1 echo $website2 運行結果: C語言中文網:${url} C語言中文網:http://c.biancheng.net
以單引號' '包圍變量的值時,單引號里面是什么就輸出什么,即使內容中有變量和命令(命令需要反引起來)也會把它們原樣輸出。這種方式比較適合定義顯示純字符串的情況,即不希望解析變量、命令等的場景。
以雙引號" "包圍變量的值時,輸出時會先解析里面的變量和命令,而不是把雙引號中的變量名和命令原樣輸出。這種方式比較適合字符串中附帶有變量和命令並且想將其解析后再輸出的變量定義。
建議:如果變量的內容是數字,那么可以不加引號;如果真的需要原樣輸出就加單引號;其他沒有特別要求的字符串等最好都加上雙引號,定義變量時加雙引號是最常見的使用場景。
將命令的結果賦值給變量
Shell 也支持將命令的執行結果賦值給變量,常見的有以下兩種方式:
variable=`command` variable=$(command)
第一種方式把命令用反引號包圍起來,反引號和單引號非常相似,容易產生混淆,所以不推薦使用這種方式;第二種方式把命令用$()包圍起來,區分更加明顯,所以推薦使用這種方式。
例如,我創建了一個名為 test 的文本文件。下面的代碼中,使用 cat 命令將 log.txt 的內容讀取出來,並賦值給一個變量,然后使用 echo 命令輸出。
[root@ken ~]# echo "this is ken" >test [root@ken ~]# mes=`cat test` [root@ken ~]# echo $mes this is ken
刪除變量
使用 unset 命令可以刪除變量。語法:
unset variable_name
變量被刪除后不能再次使用;unset 命令不能刪除只讀變量。
舉個例子:
#!/bin/bash myUrl="http://see.xidian.edu.cn/cpp/u/xitong/" unset myUrl echo $myUrl
上面的腳本沒有任何輸出。
定義只讀變量
[root@ken ~]# name=ken [root@ken ~]# readonly name [root@ken ~]# echo $name ken [root@ken ~]# unset name -bash: unset: name: cannot unset: readonly variable
變量類型
運行shell時,會同時存在三種變量:
1) 局部變量
局部變量在腳本或命令中定義,僅在當前shell實例中有效,其他shell啟動的程序不能訪問局部變量。
2) 環境變量
所有的程序,包括shell啟動的程序,都能訪問環境變量,有些程序需要環境變量來保證其正常運行。必要的時候shell腳本也可以定義環境變量。
3) shell變量
shell變量是由shell程序設置的特殊變量。shell變量中有一部分是環境變量,有一部分是局部變量,這些變量保證了shell的正常運行
特殊變量列表(shell變量)
變量 含義 $0 當前腳本的文件名 $n 傳遞給腳本或函數的參數。n 是一個數字,表示第幾個參數。例如,第一個參數是$1,第二個參數是$2。 $# 傳遞給腳本或函數的參數個數。 $* 傳遞給腳本或函數的所有參數。 $? 上個命令的退出狀態,或函數的返回值。 $$ 當前Shell進程ID。對於 Shell 腳本,就是這些腳本所在的進程ID。
請看下面的腳本:
#!/bin/bash echo "File Name: $0" echo "First Parameter : $1" echo "First Parameter : $2" echo "Quoted Values: $@" echo "Quoted Values: $*" echo "Total Number of Parameters : $#"
運行結果:
[root@ken ~]# bash test name age File Name: test First Parameter : name First Parameter : age Quoted Values: name age Quoted Values: name age Total Number of Parameters : 2
退出狀態
$? 可以獲取上一個命令的退出狀態。所謂退出狀態,就是上一個命令執行后的返回結果。
退出狀態是一個數字,一般情況下,大部分命令執行成功會返回 0,失敗返回 1。
不過,也有一些命令返回其他值,表示不同類型的錯誤。
[root@ken ~]# echo ken ken [root@ken ~]# echo $? 0 [root@ken ~]# systemctl restart jj Failed to restart jj.service: Unit not found. [root@ken ~]# echo $? 5
條件表達式
表達式 | 實例 |
[ expression ] |
[ 1 -eq 1 ] |
[[ expression ]] |
[[ 1 -eq 1 ]] |
test expression |
test 1 -eq 1 ,等同於[] |
[root@ken ~]# [ 1 -eq 2 ] && echo "this is true" || echo "this is false" this is false [root@ken ~]# [ 1 -eq 1 ] && echo "this is true" || echo "this is false" this is true
注意:括號中的表達式前后都有空格,否則會報錯!
整數比較符
比較符 |
描述 | 實例 |
-eq, equal |
等於 | [ 1 -eq 1 ] 為true |
-ne, not equal |
不等於 | [ 1 -ne 1 ] 為false |
-gt, greate than |
大於 | [ 1 -gt 1 ] 為false |
-lt, lesser than |
小於 | [ 1 -lt 1 ] 為false |
-ge, greate or equal |
大於或者等於 | [ 1 -ge 1 ] 為true |
-le, lesser or equal |
小於或者等於 | [ 1 -le 1 ] 為true |
字符串比較符
運算符 |
描述 | 實例 |
== |
等於 | [ "a" == "a" ] 為true |
!= |
不等於 | [ "a" != "a" ] 為false |
-n | 字符串長度不等於 0 為真 |
VAR1=1;VAR2="" [ -n "$VAR1" ]為 true [ -n "$VAR2" ]為 false |
-z |
字符串長度等於 0 為真 |
VAR1=1;VAR2="" [ -z "$VAR1" ]為false [ -z "$VAR2" ]為 true |
注意:使用-n 判斷字符串長度時,變量要加雙引號,養成好習慣,字符串比較時都加上雙引號。
# [ -z $a ] && echo yes || echo no yes # [ -n $a ] && echo yes || echo no yes # 加了雙引號才能正常判斷是否為空 # [ -z "$a" ] && echo yes || echo no yes # [ -n "$a" ] && echo yes || echo no no
文件測試
測試符 |
描述 | 實例 |
-e |
文件或者目錄存在為真 | [ -e path ] path 存在為 true |
-f |
文件存在為真 | [ -f file_path ] 文件存在為 true |
-d |
目錄存在為真 | [ -d dir_path ] 目錄存在為 true |
-r |
有讀權限為真 | [ -r file_path ]file_path有讀權限為真 |
-w |
有寫權限為真 | [ -r file_path ]file_path有寫權限為真 |
-x |
有執行權限為真 | [ -r file_path ]file_path有執行權限為真 |
布爾運算符
運算符 |
描述 | 實例 |
! |
非關系,條件結果取反 |
[ ! 1 -eq 2 ]為true |
-a |
和關系,在[]表達式中使用 |
[ 1 -eq 1 -a 2 -eq 2 ]為true 兩者都為真才為真 |
-o |
或關系,在[]表達式中使用 | [ 1 -eq 1 -o 2 -eq 1 ]為true 兩者有一真則為真 |
邏輯判斷符
判斷符 | 描述 | 實例 |
&& |
邏輯和,在[[]]表達式中 或判斷表達式是否為真時使用 |
[[ 1 -eq 1 && 2 -eq 2 ]]為 true [ 1 -eq 1 ] && echo 'true',如果&&前面的 表達式為true則執行后面的 |
|| |
邏輯或,在[[]]表達式中 或判斷表達式是否為真時使用 |
[[ 1 -eq 1 || 2 -eq 1 ]]為 true [ 1 -eq 2 ] || echo 'true',如果||前面的 表達式為false則執行后面的 |
注意:[] 不支持以上兩個邏輯判斷符,應該使用布爾運算符
整數運算
運算符 |
描述 |
+ |
加法 |
- |
減法 |
* |
乘法 |
/ |
除法 |
% |
取余 |
運算表達式 |
實例 |
$(()) |
$((1+1)) |
$[] |
$[] |
其他運算工具
命令 | 描述 |
實例 |
let | 賦值並運算,支持++、-- |
let VAR=(1+2)*3 ; echo $VAR x=10 ; y=5 let x++;echo $x 每執行一次 x 加 1 let y--;echo $y 每執行一次 y 減 1 let x+=2 每執行一次 x 加 2 let x-=2 每執行一次 x 減 2 |
expr | 乘法*需要加反斜杠轉義\* |
expr 1 \* 2 運算符兩邊必須有空格 expr \( 1 + 2 \) \* 2 使用雙括號時要轉義 |
bc | 計算器,支持浮點運算、平方等 |
bc 本身就是一個計算器,可直接輸入命令,進入解釋器 echo 1 + 2 |bc 將管道符前面標准輸出作為 bc 的標准輸入 echo "1.2+2" |bc |
shell括號用途總結