Shell腳本和Shell程序
業(yè)界所說的 shell 通常都是指 shell 腳本,但要知道,shell 和 shell script 是兩個不同的概念。
Shell 腳本(shell script),是一種為 shell 編寫的腳本程序。
Shell程序 是一個用 C 語言編寫的程序,它是用戶使用 Linux 的橋梁。Shell程序 是指一種應(yīng)用程序,這個應(yīng)用程序提供了一個界面,用戶通過這個界面訪問操作系統(tǒng)內(nèi)核的服務(wù)。
由于習(xí)慣的原因,簡潔起見,本文出現(xiàn)的 "shell編程" 都是指 shell 腳本編程,不是指開發(fā) shell 自身。
shell環(huán)境
Shell 編程跟 JavaScript、php 編程一樣,只要有一個能編寫代碼的文本編輯器和一個能解釋執(zhí)行的腳本解釋器就可以了。
Linux 的 Shell 種類眾多,常見的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
由于易用和免費(fèi),Bash 在日常工作中被廣泛使用。同時,Bash 也是大多數(shù)Linux 系統(tǒng)默認(rèn)的 Shell。
在一般情況下,人們并不區(qū)分 Bourne Shell 和 Bourne Again Shell,所以,像 #!/bin/sh,它同樣也可以改為 #!/bin/bash。
! 告訴系統(tǒng)用那種解析器來解析當(dāng)前的shell腳本
第一個shell腳本
通過touch helloworld.sh新建一個shell腳本,同時通過vi/vim helloworld.sh進(jìn)入shell文件進(jìn)行編寫
關(guān)于vi/vim的編輯器的使用可以參考:
Linux vi/vim
shell腳本的運(yùn)行
運(yùn)行 Shell 腳本有兩種方法:
1、作為可執(zhí)行程序
將上面的代碼保存為 hellowrold.sh,并 cd 到相應(yīng)目錄,
chmod +x ./test.sh #使腳本具有執(zhí)行權(quán)限
./test.sh #執(zhí)行腳本
注意,一定要寫成 ./hellowrold.sh,而不是 hellowrold.sh,運(yùn)行其它二進(jìn)制的程序也一樣,直接寫 hellowrold.sh,linux 系統(tǒng)會去 PATH 里尋找有沒有叫 hellowrold.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的當(dāng)前目錄通常不在 PATH 里,所以寫成 hellowrold.sh 是會找不到命令的,要用 ./hellowrold.sh 告訴系統(tǒng)說,就在當(dāng)前目錄找。
2、作為解釋器參數(shù)
這種運(yùn)行方式是,直接運(yùn)行解釋器,其參數(shù)就是 shell 腳本的文件名,如:
/bin/sh hellowrold.sh ## 可以簡寫為sh hellowrold.sh
/bin/bash hellowrold.php ## 可以簡寫為bash hellowrold.sh
這種方式運(yùn)行的腳本,不需要在第一行指定解釋器信息,寫了也沒用.
shell變量
- 語法格式:變量名=變量值
變量名的命名須遵循如下規(guī)則:
- 變量名和等號之間不能有空格
- 變量名首個字符必須為英文字母
- 不能包含標(biāo)點(diǎn)符號但能夠使用下劃線(_)
- 不能使用空格
- 不能使用 bash 里的關(guān)鍵字
- 變量類型
| 類型 | 解釋 |
|---|---|
| 局部變量 | 局部變量在腳本或命令中定義,僅在當(dāng)前shell實(shí)例中有效,其他shell啟動的程序不能訪問局部變量 |
| 環(huán)境變量 | 所有的程序,包括shell啟動的程序,都能訪問環(huán)境變量,有些程 序需要環(huán)境變量來保證其正常運(yùn)行。可以用過set命令查看當(dāng)前環(huán)境變量 |
| shell變量 | 由shell程序設(shè)置的特殊變量。shell變量中有一部分是環(huán)境變量,有一部分是局部變量,這些變量保證了shell 的正常運(yùn)行 |
變量的使用
- 定義變量
name="定義變量"
readonly name
name="改變只讀變量的值" # 報錯
使用readonly命令可以將變量定義為只讀變量,只讀變量的值不能被改變
- 引用變量
name="引用變量"
echo ${name}
echo $name
引用一個定義過的變量,只要在變量名前面加$即可,變量名外面的花括號是可選的,加不加都行,加花括號是為了幫助解釋器識別變量的邊界。
- 重新定義變量(變量的重新賦值)
name="定義變量"
echo ${name}
name="變量的重新賦值"
echo ${name}
- 刪除變量
name="定義變量"
unset name
echo $name
使用unset命令可以刪除變量,變量被刪除后不能再次使用,同時unset命令不能刪除只讀變量。
參數(shù)傳遞
在執(zhí)行Shell腳本時,可以向腳本傳遞參數(shù)。腳本內(nèi)獲取參數(shù)的格式為:$n。n代表一個數(shù)字,1為執(zhí)行腳本的第一個參數(shù),2為執(zhí)行腳本的第二個參數(shù),以此類推…
- 改helloworld.sh為
#!/bin/bash
echo $1
echo $2
echo $3
- 行攜帶參數(shù)
[root@centos6-1 ~]# ./helloworld.sh haha wowow nini
haha
wowow
nini
[root@centos6-1 ~]#
shell字符串
shell字符串串可以用單引號,也可以用雙引號,也可以不用引號
- 單引號
name='my name is string'
單引號字符串中不支持引用變量,任何字符都會原樣輸出
單引號字串中不能出現(xiàn)單引號(對單引號使用轉(zhuǎn)義符后也不行)
- 雙引號
name='my name is string'
name_again="\"${name}\""
雙引號里可以引有變量
雙引號里支持轉(zhuǎn)義字符
- 字符串長度
name='my name is string'
echo ${#name} //執(zhí)行輸出為17
- 截取字符串
string="runoob is a great site"
echo ${string:1:4} # 輸出 unoo
從字符串第 2 個字符開始截取 4 個字符
注意:第一個字符的索引值為 0
- 查找子字符串
查找字符 i 或 o 的位置(哪個字母先出現(xiàn)就計(jì)算哪個):
string="runoob is a great site"
echo `expr index "$string" io` # 輸出 4
注意: 以上腳本中 ` 是反引號,而不是單引號 ',不要看錯了哦。
shell數(shù)組
bash支持一維數(shù)組(不支持多維數(shù)組),并且沒有限定數(shù)組的大小。
類似于 C 語言,數(shù)組元素的下標(biāo)由 0 開始編號。獲取數(shù)組中的元素要利用下標(biāo),下標(biāo)可以是整數(shù)或算術(shù)表達(dá)式,其值應(yīng)大于或等于 0。
- 定義數(shù)組
在 Shell 中,用括號來表示數(shù)組,數(shù)組元素用"空格"符號分割開。定義數(shù)組的一般形式為:
數(shù)組名=(值1 值2 ... 值n)
例如:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
還可以單獨(dú)定義數(shù)組的各個分量:
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
可以不使用連續(xù)的下標(biāo),而且下標(biāo)的范圍沒有限制。
- 讀取數(shù)組
讀取數(shù)組元素值的一般格式是:
${數(shù)組名[下標(biāo)]}
例如:
valuen=${array_name[n]}
使用 @ 符號可以獲取數(shù)組中的所有元素,例如:
echo ${array_name[@]}
- 獲取數(shù)組的長度
獲取數(shù)組長度的方法與獲取字符串長度的方法相同,例如:
# 取得數(shù)組元素的個數(shù)
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得數(shù)組單個元素的長度
lengthn=${#array_name[n]}
shell 注釋
單行注釋
使用#,通過每一行加一個#號設(shè)置多行注釋多行注釋
:<<EOF
注釋內(nèi)容...
注釋內(nèi)容...
注釋內(nèi)容...
EOF
或者
:<<!
注釋內(nèi)容...
注釋內(nèi)容...
注釋內(nèi)容...
!
shell流程控制
if
和Java、PHP等語言不一樣,sh的流程控制不可為空,如(以下為PHP流程控制寫法):
<?php
if (isset($_GET["q"])) {
search(q);
}
else {
// 不做任何事情
}
在sh/bash里可不能這么寫,如果else分支沒有語句執(zhí)行,就不要寫這個else。
- if 語句語法格式:
if condition
then
command1
command2
...
commandN
fi
末尾的fi就是if倒過來拼寫
- if else 語法格式:
if condition
then
command1
command2
...
commandN
else
command
fi
- if else-if else 語法格式:
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
for循環(huán)
for循環(huán)一般格式為:
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
例如:順序輸出列表中的字符
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
輸出結(jié)果:
The value is: 1
The value is: 2
The value is: 3
The value is: 4
The value is: 5
順序輸出字符串中的字符:
for str in 'This is a string'
do
echo $str
done
輸出結(jié)果:
This is a string