一、shell腳本
shell腳本語言是解釋性語言,其本質是shell指令的有序集合。
shell腳本在此處有講解
二、shell程式設計步驟
-
建立shell檔案
vi shell.sh
-
更改權限
chmod 777 shell.sh
0 7 7 7 6 6 6 rwx rwx rwx rw-rw-rw- 111 111 111 110110110
-
執行shell腳本
./shell.sh
三、shell變量
定義變量
variable=value
variable='value'
variable="value"
#variable 是變量名,value 是賦給變量的值。如果 value 不包含任何空白符(例如空格、Tab 縮進等),那麼可以不使用引号;如果 value 包含了空白符,那麼就必須使用引号包圍起來。使用單引号和使用雙引号也是有差別的,稍後我們會詳細說明
注意:
指派号=的周圍不能有空格,這可能和你熟悉的大部分程式設計語言都不一樣。
定義變量時盡量全部大寫,避免與指令同名(規定)。
shell變量沒有資料類型。
使用變量
#使用一個定義過的變量,隻要在變量名前面加美元符号$即可,如:
author="張三"
echo $author
echo ${author}
#變量名外面的花括号{ }是可選的,加不加都行,加花括号是為了幫助解釋器識别變量的邊界,比如下面這種情況:
skill="Java"
echo "I am good at ${skill}Script"
#如果不給 skill 變量加花括号,寫成echo "I am good at $skillScript",解釋器就會把 $skillScript 當成一個變量(其值為空),代碼執行結果就不是我們期望的樣子了。推薦給所有變量加上花括号{ },這是個良好的程式設計習慣。
注意:
let 表達式 可以讓表達式以c語言的風格計算。eg:let sum+=i ;let ++i;
`` 用在兩條指令時讓被小引号包裹的内容會先執行。eg:echo `expr $sum + 1`
修改變量的值
#已定義的變量,可以被重新指派,如:
url="ABC"
echo ${url}
url="abc"
echo ${url}
#第二次對變量指派時不能在變量名前加$,隻有在使用變量時才能加$。
單引号和雙引号的差別
url="ABC"
out1='輸出:${url}'
out2="輸出:${url}"
url="輸出:${url}"
echo $out1
echo $out2
#運作結果:
#輸出:${url}
#輸出:ABC
#以單引号' '包圍變量的值時,單引号裡面是什麼就輸出什麼,即使内容中有變量和指令(指令需要反引起來)也會把它們原樣輸出。這種方式比較适合定義顯示純字元串的情況,即不希望解析變量、指令等的場景。
#以雙引号" "包圍變量的值時,輸出時會先解析裡面的變量和指令,而不是把雙引号中的變量名和指令原樣輸出。這種方式比較适合字元串中附帶有變量和指令并且想将其解析後再輸出的變量定義。
将指令的結果指派給變量
#Shell 也支援将指令的執行結果指派給變量,常見的有以下兩種方式:
variable=`command`
variable=$(command)
隻讀變量
使用 readonly
下面的例子嘗試更改隻讀變量,結果報錯:運作腳本,結果如下:
myUrl="ABC"
readonly myUrl
myUrl="abc"
#運作結果:myUrl: This variable is read only.
删除變量
使用 unset
unset variable_name
#變量被删除後不能再次使用;unset 指令不能删除隻讀變量。
#舉個例子:
myUrl="ABC"
unset myUrl
echo $myUrl
#上面的腳本沒有任何輸出
四、shell數組
定義數組
#在 Shell 中,用括号( )來表示數組,數組元素之間用空格來分隔。由此,定義數組的一般形式為:
array_name=(ele1 ele2 ele3 ... elen) # =号兩端不能有空格
#Shell 是弱類型的,它并不要求所有數組元素的類型必須相同,例如:
arr=(20 56 "ABC") #前面兩個元素都是整數,而第三個元素是字元串
#Shell 數組的長度不是固定的,定義之後還可以增加元素。
arr[6]=88
#此外,你也無需逐個元素地給數組指派,下面的代碼就是隻給特定元素指派:
arr=([3]=24 [5]=19 [10]=12)
數組操作
#通路數組元素 index 是數組下标
${array_name[index]}
#給數組元素指派
array_name[index]=6
#求數組元素個數
${#array_name[@]}或者${#array_name[*]}
#周遊數組元素
${array_name[@]}或者${array_name[*]}
五、shell特殊變量
$$:目前程序的程序号(PID),對于 Shell 腳本,就是這些腳本所在的程序ID
$! :功能描述:背景運作的最後一個程序的程序号(PID)
$?:功能描述:最後一次執行的指令的傳回狀态,或函數的傳回值
$#:傳遞給腳本或函數的參數個數
$*:傳遞給腳本或函數的所有參數
[email protected]: 傳遞給腳本或函數的所有參數,被雙引号(" ")包含時,與 $* 稍有不同,下面将會講到
$0:目前腳本的檔案名
$1 - $9 :指令行的第一個到第九個參數
$*與[email protected]的差別
$*和[email protected]都可以用來輕松通路所有的參數,隻不過$*會将這些參數視為一個整體,而不是多個個體。[email protected]會将所有參數當作同一字元串中的多個獨立的單詞
echo "Usint the \$* method: $*"
echo "Using the \[email protected] method: [email protected]"
count=1
for param in "$*"
do
echo "\$* params #$count = $param"
count=$[ $count + 1 ]
done
count=1
for param in "[email protected]"
do
echo "\[email protected] params #$count = $param"
count=$[ $count + 1 ]
done
#執行結果
Usint the \$* method: a b c
Usint the \$* method: a b c
$* params #1 = a b c
[email protected] params #1 = a
[email protected] params #2 = b
[email protected] params #3 = c
六、shell環境變量
了解環境變量
環境變量是在作業系統中一個具有特定名字的對象,它包含了一個或多個應用程式将使用到的資訊。Linux是一個多使用者的作業系統,每個使用者登入系統時都會有一個專用的運作環境,通常情況下每個使用者的預設的環境都是相同的。這個預設環境就是一組環境變量的定義。每個使用者都可以通過修改環境變量的方式對自己的運作環境進行配置。
常用的幾個環境變量:
PATH
指定指令的搜尋路徑。通過設定環境變量PATH可以讓我們運作程式或指令更加友善。
echo $PATH 檢視環境變量PATH。
每一個冒号都是一個路徑,這些搜尋路徑都是一些可以找到可執行程式的目錄清單。當我們輸入一個指令時,shell會先檢查指令是否是内部指令,不是的話會再檢查這個指令是否是一個應用程式。然後shell會試着從搜尋路徑,即PATH中尋找這些應用程式。如果shell在這些路徑目錄裡沒有找到可執行檔案。則會報錯。若找到,shell内部指令或應用程式将被分解為系統調用并傳給Linux核心。
舉個例子:
現在有一個c程式test.c通過gcc編譯生成的可執行檔案a.out(功能:輸出helloworld)。我們平常執行這個a.out的時候是使用三種方法:
1.相對路徑調用: ./a.out (”.”代表目前目錄,”/”分隔符)
2.絕對路徑調用:/home/lzk/test/a.out
3.通過設定PATH環境變量,直接用檔案名調用: a.out (隻要可以通過PATH中路徑找得到這個可執行檔案)
HOME
指定使用者的主工作目錄,即為使用者登入到Linux系統中時的預設目錄,即“~”。
HISTSIZE
指儲存曆史指令記錄的條數。我們輸入的指令都會被系統儲存下來,這個環境變量記錄的就是保持指令的條數。一般為1000。
這些曆史指令都被儲存在使用者工作主目錄“~”下的隐藏檔案.bash_profile中。
我們可以通過指令history來檢視。
LOGNAME
指目前使用者的登入名。
HOSTNAME
指主機的名稱。
SHELL
指目前使用者用的是哪種shell。
LANG/LANGUGE
和語言相關的環境變量,使用多種語言的使用者可以修改此環境變量。
指目前使用者的郵件存放目錄。
PS1
第一級Shell指令提示符,root使用者是#,普通使用者是$。
PS2
第二級指令提示符,預設是“>”。
PS3
第三級指令提示符。主要用于select循環控制結構的菜單選擇提示符 :【等待一個連結】。
TMOUT
使用者和系統互動過程的逾時值。
系統與使用者進行互動時,系統提示讓使用者進行輸入,但使用者遲遲沒有輸入,時間超過TMOUT設定的值後,shell将會因逾時而終止執行。
小結
環境變量是和shell緊密相關的,使用者登入系統後就啟動了一個shell,對于Linux來說一般是bash(Bourne Again shell,Bourne shell(sh)的擴充),也可以切換到其他版本的shell。
bash有兩個基本的系統級配置檔案:/etc/bashrc和/etc/profile。這些配置檔案包含了兩組不同的變量:shell變量和環境變量。shell變量是局部的,而環境變量是全局的。環境變量是通過shell指令來設定。設定好的環境變量又可以被是以目前使用者的程式使用。
七、shell的功能語句
read
從終端讀取一行資料,寫入read後的變量
read var var1 var2
expr
算術運算
tmp=`expr $I + 1`
注意:乘法運算符:\*
test
test可了解的表達式類型分為四類:
判斷表達式
if test ------(表達式為真)
if test !------表達式為假
test 表達式1 –a 表達式2------兩個表達式都為真
test 表達式1 –o 表達式2------兩個表達式有一個為真
判斷字元串
test –n 字元串------字元串的長度非零
test –z 字元串------字元串的長度為零
test 字元串1=字元串2------字元串相等
test 字元串1 !=字元串2------字元串不等
判斷整數
test 整數1 –eq 整數2------整數相等
test 整數 1 –ge 整數2------整數1大于等于整數2
test 整數1 –gt 整數2------整數1大于整數2
test 整數1 –le 整數2------整數1小于等于整數2
test 整數1 –lt 整數2------整數1小于整數2
test 整數1 –ne 整數2------整數1不等于整數2
判斷檔案
test File1 –ef File2------兩個檔案具有同樣的裝置号和i結點号
test File1 –nt File2------檔案1比檔案2 新
test File1 –ot File2------檔案1比檔案2 舊
test –b File------檔案存在并且是塊裝置檔案
test –c File------檔案存在并且是字元裝置檔案
test –d File------檔案存在并且是目錄
test –e File------檔案存在
test –f File------檔案存在并且是正規檔案
test –g File------檔案存在并且是設定了組ID
test –G File------檔案存在并且屬于有效組ID
test –h File------檔案存在并且是一個符号連結(同-L)
test –k File------檔案存在并且設定了sticky位
test –b File------檔案存在并且是塊裝置檔案
test –L File------檔案存在并且是一個符号連結(同-h)
test –o File------檔案存在并且屬于有效使用者ID
test –p File------檔案存在并且是一個命名管道
test –r File------檔案存在并且可讀
test –s File------檔案存在并且是一個套接字
test –t File------檔案描述符是在一個終端打開的
test –u File------檔案存在并且設定了它的set-user-id位
test –w File------檔案存在并且可寫
test –x File------檔案存在并且可執行
注意:
test xxx 可以簡寫成 [ xxx ] 的形式。
在使用"[]"簡寫test時,左括号後面的空格和右括号前面的空格是必需的,如果沒有空格,Shell不可能辨識表達式何時開始何時結束.
也就是說:test option file
可以全部改寫成:[ option file ]
例如::test –w File
改寫成:[ –w File ]
八、shell函數
函數定義
#第一種--如果你嫌麻煩,函數定義時也可以不寫 function 關鍵字
name()
{
statements
[return value]
}
#第二種--如果寫了 function 關鍵字,也可以省略函數名後面的小括号
function name
{
statements
[return value]
}
#建議使用第二種,這樣能夠做到"見名知意"
函數調用
調用 Shell 函數時可以給它傳遞參數,也可以不傳遞。如果不傳遞參數,直接給出函數名字即可
name
如果傳遞參數,那麼多個參數之間以空格分隔
name param1 param2 param3
不管是哪種形式,函數名字後面都不需要帶括号。
和其它程式設計語言不同的是,Shell 函數在定義時不能指明參數,但是在調用時卻可以傳遞參數,并且給它傳遞什麼參數它就接收什麼參數。
Shell 也不限制定義和調用的順序,你可以将定義放在調用的前面,也可以反過來,将定義放在調用的後面。
示例:
function getsum
{
local sum=0
for n in [email protected]
do
((sum+=n))
done
return $sum
}
getsum 10 20 55 15 #調用函數并傳遞參數
echo $?
#在函數内shell特殊變量就由調用函數時傳入的參數決定
#函數傳回值,隻能通過$?系統變量獲得,直接通過=獲得是空值,可以把函數了解成一個指令
#在shell中獲得指令傳回值,都需要通過$?獲得
九、shell結構性語句
條件測試語句
if ... then ... fi
if 表達式
then
指令表
fi
#如果表達式為真,則執行then 後的指令表
if ... then ... else ... fi
if 表達式
then 指令表1
else 指令表2
fi
#如果表達式為真,則執行 指令表1,
#否則,執行指令表 2
if ... then ... elif ... then ... fi
if 表達式1
then
指令表1
elif 表達式2
then
指令表2
fi
#如果表達式1 為真,則執行 指令表1
#如果表達式2 為真,則執行 指令表2
多路分支語句
case 變量 in
模式1)
指令表 1 ;;
模式2 | 模式3)
指令表 2 ;;
模式4)
指令表 3 ;;
*)
指令表 4 ;;
esac
#case 多路分支語句隻能判斷字元串
循環語句
for 變量名 in 單詞表
do
指令表
done
eg:
for i in 1 2 3 4 5 6 7 8 9 10 //常用單詞表格式
do
....
done
for i in {1..10} //單詞表新式用法,指定一個範圍
do
...
done
#注意:
#變量 每取單詞表中的一個單詞,循環進行一次,
#單詞表中的單詞個數,決定循環的額次數
while 表達式1
do
指令表 1
done
#注意:
#如果表達式為真則進入循環,執行指令表1
#如果表達式為假則退出循環