Shell變量
(1)定義變量的時候,賦值號=
周圍不能有空格
(2)定義變量時不需要$
符號,而使用變量時可以用$var
或這${var}
,推薦使用${}
的方式,便於解釋器識別變量邊界。
name="Lethe"
echo ${name}
(3)單引號與雙引號的區別
- 單引號
''
包圍變量的值時,單引號裏面是什麼就輸出什麼,即使內容中有變量和命令(命令需要反引起來)也會把它們原樣輸出。 - 雙引號
""
包圍變量的值時,輸出時會先解析裏面的變量和命令。
(4)將命令的執行結果賦給一個變量有下面兩種方式:
- 反引號
$()
(推薦使用)
(5)計算表達式:$(())
(6)通過readonly
可以將變量聲明爲只讀變量,只讀變量不能被改變,也不能被unset
命令刪除。
Shell特殊變量
(1)特殊變量列表
變量 | 含義 |
---|---|
$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 : $#"
(2)$*
和 $@
的區別
$*
和 $@
都表示傳遞給函數或腳本的所有參數,不被雙引號(" ")
包含時,都以"$1" "$2" … "$n"
的形式輸出所有參數。
但是當它們被雙引號(" ")
包含時:
"$*"
會將所有的參數作爲一個整體,以"$1 $2 … $n"
的形式輸出所有參數;"$@"
會將各個參數分開,以"$1" "$2" … "$n"
的形式輸出所有參數。
Shell替換
(1)如果表達式中包含特殊字符,Shell 將會進行替換。例如,在雙引號中使用變量就是一種替換,轉義字符也是一種替換。
這裏 -e 表示對轉義字符進行替換。如果不使用 -e 選項,將會原樣輸出。
下面的轉義字符都可以用在 echo 中:
轉義字符 | 含義 |
---|---|
\\ | 反斜槓 |
\a | 警報,響鈴 |
\b | 退格(刪除鍵) |
\f | 換頁(FF),將當前位置移到下頁開頭 |
\n | 換行 |
\r | 回車 |
\t | 水平製表符(tab鍵) |
\v | 垂直製表符 |
也可以使用 echo 命令的 -E 選項禁止轉義,默認也是不轉義的;使用 -n 選項可以禁止插入換行符。
(2)命令替換
命令替換是指Shell可以先執行命令,將輸出結果暫時保存,在適當的地方輸出。
(3)變量替換
變量替換可以根據變量的狀態(是否爲空、是否定義等)來改變它的值。
可以使用的變量替換形式:
形式 | 說明 |
---|---|
${var} | 變量本來的值 |
${var:-word} | 如果變量 var 爲空或已被刪除(unset),那麼返回 word,但不改變 var 的值。 |
${var:=word} | 如果變量 var 爲空或已被刪除(unset),那麼返回 word,並將 var 的值設置爲 word。 |
${var:?message} | 如果變量 var 爲空或已被刪除(unset),那麼將消息 message 送到標準錯誤輸出,可以用來檢測量 var 是否可以被正常賦值。若此替換出現在Shell腳本中,那麼腳本將停止運行。 |
${var:+word} | 如果變量 var 被定義,那麼返回 word,但不改變 var 的值。 |
#!/bin/bash
echo ${var:-"Variable is not set"}
echo "1 - Value of var is ${var}"
echo ${var:="Variable is not set"}
echo "2 - Value of var is ${var}"
unset var
echo ${var:+"This is default value"}
echo "3 - Value of var is $var"
var="Prefix"
echo ${var:+"This is default value"}
echo "4 - Value of var is $var"
echo ${var:?"Print this message"}
echo "5 - Value of var is ${var}"
Shell運算符
(1)原生bash不支持簡單的數學運算,但是可以通過其他命令來實現,例如 awk 和 expr,expr 最常用。
- 表達式和運算符之間要有空格,例如 2+2 是不對的,必須寫成 2 + 2
- 完整的表達式要被反引號包含
(2)算數運算符
運算符 | 說明 | 舉例 |
---|---|---|
+ | 加法 | `expr $a + $b` 結果爲 30。 |
- | 減法 | `expr $a - $b` 結果爲 10。 |
* | 乘法 | `expr $a * $b` 結果爲 200。 |
/ | 除法 | `expr $b / $a` 結果爲 2。 |
% | 取餘 | `expr $b % $a` 結果爲 0。 |
= | 賦值 | a=$b 將把變量 b 的值賦給 a。 |
== | 相等。用於比較兩個數字,相同則返回 true。 | [ $a == $b ] 返回 false。 |
!= | 不相等。用於比較兩個數字,不相同則返回 true。 | [ $a != $b ] 返回 true。 |
- 乘號(*)前邊必須加反斜槓()才能實現乘法運算;
- 條件表達式要放在方括號之間,並且要有空格,例如
[$a==$b]
是錯誤的,必須寫成[ $a == $b ]
(3)關係運算符
關係運算符只支持數字,不支持字符串,除非字符串的值是數字。
運算符 | 說明 | 舉例 |
---|---|---|
-eq | 檢測兩個數是否相等,相等返回 true,相當於== | [ $a -eq $b ] 返回 true。 |
-ne | 檢測兩個數是否相等,不相等返回 true,相當於!= | [ $a -ne $b ] 返回 true。 |
-gt | 檢測左邊的數是否大於右邊的,如果是,則返回 true,相當於> | [ $a -gt $b ] 返回 false。 |
-lt | 檢測左邊的數是否小於右邊的,如果是,則返回 true,相當於< | [ $a -lt $b ] 返回 true。 |
-ge | 檢測左邊的數是否大等於右邊的,如果是,則返回 true,相當於>= | [ $a -ge $b ] 返回 false。 |
-le | 檢測左邊的數是否小於等於右邊的,如果是,則返回 true,相當於<= | [ $a -le $b ] 返回 true。 |
(4)布爾運算符
運算符 | 說明 | 舉例 |
---|---|---|
! | 非運算,表達式爲 true 則返回 false,否則返回 true。 | [ ! false ] 返回 true。 |
-o | 或運算,有一個表達式爲 true 則返回 true。 | [ $a -lt 20 -o $b -gt 100 ] 返回 true。 |
-a | 與運算,兩個表達式都爲 true 才返回 true。 | [ $a -lt 20 -a $b -gt 100 ] 返回 false。 |
(5)字符串運算符
運算符 | 說明 | 舉例 |
---|---|---|
= | 檢測兩個字符串是否相等,相等返回 true。 | [ $a = $b ] 返回 false。 |
!= | 檢測兩個字符串是否相等,不相等返回 true。 | [ $a != $b ] 返回 true。 |
-z | 檢測字符串長度是否爲0,爲0返回 true。 | [ -z $a ] 返回 false。 |
-n | 檢測字符串長度是否爲0,不爲0返回 true。 | [ -z $a ] 返回 true。 |
str | 檢測字符串是否爲空,不爲空返回 true。 | [ $a ] 返回 true。 |
Shell註釋
-
以“#”開頭的行就是註釋,會被解釋器忽略。
-
sh裏沒有多行註釋,只能每一行加一個#號
Shell字符串
(1)拼接字符串
string1="Hello"
string2="World"
echo $string1 $string2 # 輸出Hello World
(2)獲取字符串長度
string="abcd"
echo ${#string} #輸出 4
(3)提取子字符串
string="Hello Word"
echo ${string:1:4} #輸出ello
(4)查找子字符串
string="Hello World"
echo `expr index "$string" lo` # 輸出3
Shell數組
(1)定義數組
在Shell中,用括號來表示數組,數組元素用“空格”符號分割開
array_name=(value0 value1 value2 value3)
或單獨定義數組的各個分量:
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
可以不使用連續的下標,而且下標的範圍沒有限制。
(2)讀取數組
讀取數組格式:${array_name[index]}
valuen=${array_name[2]}
- 使用
@
或*
可以獲取數組中的所有元素。
${array_name[*]}
${array_name[@]}
- 獲取數組長度的方法與獲取字符串長度的方法相同
# 取得數組元素的個數
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得數組單個元素的長度
lengthn=${#array_name[n]}
if else語句
(1)if … else 語句
if [ expression ]
then
Statement(s) to be executed if expression is true
fi
- 如果 expression 返回 true,then 後邊的語句將會被執行;如果返回 false,不會執行任何語句。
- 最後必須以 fi 來結尾閉合 if。
- expression 和方括號([ ])之間必須有空格,否則會有語法錯誤。
(2)if … else … fi 語句
if [ expression ]
then
Statement(s) to be executed if expression is true
else
Statement(s) to be executed if expression is not true
fi
如果 expression 返回 true,那麼 then 後邊的語句將會被執行;否則,執行 else 後邊的語句。
(3)if … elif … fi 語句
if [ expression 1 ]
then
Statement(s) to be executed if expression 1 is true
elif [ expression 2 ]
then
Statement(s) to be executed if expression 2 is true
elif [ expression 3 ]
then
Statement(s) to be executed if expression 3 is true
else
Statement(s) to be executed if no expression is true
fi
哪一個 expression 的值爲 true,就執行哪個 expression 後面的語句;如果都爲 false,那麼不執行任何語句。
(4)if … else 語句也可以寫成一行,以命令的方式來運行,像這樣:
if test $[2*3] -eq $[1+5]; then echo 'The two numbers are equal!'; fi;
test 命令用於檢查某個條件是否成立,與方括號([ ])類似。
case esac語句
case 語句匹配一個值或一個模式,如果匹配成功,執行相匹配的命令,與其他語言的switch … case類似。
case語句格式如下:
case 值 in
模式1)
command1
command2
command3
;;
模式2)
command1
command2
command3
;;
*)
command1
command2
command3
;;
esac
例子:
#!/bin/bash
option="${1}"
case ${option} in
-f) FILE="${2}"
echo "File name is $FILE"
;;
-d) DIR="${2}"
echo "Dir name is $DIR"
;;
*)
echo "`basename ${0}`:usage: [-f file] | [-d directory]"
exit 1 # Command to come out of the program with status 1
;;
esac
運行結果:
$./test.sh
test.sh: usage: [ -f filename ] | [ -d directory ]
$ ./test.sh -f index.htm
$ vi test.sh
$ ./test.sh -f index.htm
File name is index.htm
$ ./test.sh -d unix
Dir name is unix
$
for循環
格式如下:
for 變量 in 列表
do
command1
command2
...
commandN
done
-
列表是一組值(數字、字符串等)組成的序列,每個值通過空格分隔。每循環一次,就將列表中的下一個值賦給變量。
-
in 列表是可選的,如果不用它,for 循環使用命令行的位置參數。
#!/bin/bash
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
while循環
while循環用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令通常爲測試條件。其格式爲:
while command
do
Statement(s) to be executed if command is true
done
例子:
#!/bin/bash
count=0
while [ $count -lt 5]
do
count=`expr $count + 1`
echo $count
done
until循環
until 循環執行一系列命令直至條件爲 true 時停止。until 循環與 while 循環在處理方式上剛好相反。
until command
do
Statement(s) to be executed until command is true
done
break和continue命令
(1)break
- break命令允許跳出所有循環(終止執行後面的所有循環)。
- 在嵌套循環中,break 命令後面還可以跟一個整數,表示跳出第幾層循環。例如:
break n
表示跳出第 n 層循環。
(2)continue
- continue命令與break命令類似,只有一點差別,它不會跳出所有循環,僅僅跳出當前循環。
- continue 後面也可以跟一個數字,表示跳出第幾層循環。
Shell函數
Shell函數的定義格式如下:
function_name() {
list of commands
[ return value ]
}
Shell 函數返回值只能是整數,一般用來表示函數執行成功與否,0表示成功,其他值表示失敗。
如果 return 其他數據,比如一個字符串,往往會得到錯誤提示:“numeric argument required”。
如果一定要讓函數返回字符串,那麼可以先定義一個變量,用來接收函數的計算結果,腳本在需要的時候訪問這個變量來獲得函數返回值。
例子:
#!/bin/bash
funWithReturn(){
echo "The function is to get the sum of two numbers..."
echo -n "Input first number: "
read aNum
echo -n "Input another number: "
read anotherNum
echo "The two numbers are $aNum and $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
# Capture value returnd by last command
ret=$?
echo "The sum of two numbers is $ret !"
在函數內部可以用 $n 的形式來獲取參數的值,例如,$1表示第一個參數,$2表示第二個參數…
特殊變量 | 說明 |
---|---|
$# | 傳遞給函數的參數個數。 |
$* | 顯示所有傳遞給函數的參數。 |
$@ | 與$*相同,但是略有區別,請查看Shell特殊變量。 |
$? | 函數的返回值。 |
輸入輸出重定向
一般情況下,每個 Unix/Linux 命令運行時都會打開三個文件:
- 標準輸入文件(stdin):stdin的文件描述符爲0,Unix程序默認從stdin讀取數據。
- 標準輸出文件(stdout):stdout 的文件描述符爲1,Unix程序默認向stdout輸出數據。
- 標準錯誤文件(stderr):stderr的文件描述符爲2,Unix程序會向stderr流中寫入錯誤信息
命令 | 說明 |
---|---|
command > file | 將輸出重定向到 file。 |
command < file | 將輸入重定向到 file。 |
command >> file | 將輸出以追加的方式重定向到 file。 |
n > file | 將文件描述符爲 n 的文件重定向到 file。 |
n >> file | 將文件描述符爲 n 的文件以追加的方式重定向到 file。 |
n >& m | 將輸出文件 m 和 n 合併。 |
n <& m | 將輸入文件 m 和 n 合併。 |
<< tag | 將開始標記 tag 和結束標記 tag 之間的內容作爲輸入。 |
Shell文件包含
Shell 中包含腳本可以使用:
. filename
或
source filename
通常使用點號.
,注意點號.
和文件名中間有一空格。