shell腳本程式設計總結
shell是什麼;
Shell是系統的使用者界面,提供了使用者與核心進行互動操作的一種接口。它接收使用者輸入的指令并把它送入核心去執行。
實際上Shell是一個指令解釋器,它解釋由使用者輸入的指令并且把它們送到核心。不僅如此,Shell有自己的程式設計語言用于對指令的編輯,它允許使用者編寫由shell指令組成的程式。Shell程式設計語言具有普通程式設計語言的很多特點,比如它也有循環結構和分支控制結構等,用這種程式設計語言編寫的Shell程式與其他應用程式具有同樣的效果。
Linux提供了像MicrosoftWindows那樣的可視的指令輸入界面--X Window的圖形使用者界面(GUI)。它提供了很多桌面環境系統,其操作就像Windows一樣,有視窗、圖示和菜單,所有的管理都是通過滑鼠控制。GNOME。
shell的種類
每個Linux系統的使用者可以擁有他自己的使用者界面或Shell,用以滿足他們自己專門的Shell需要。
同Linux本身一樣,Shell也有多種不同的版本。主要有下列版本的Shell: Bourne Shell:是貝爾實驗室開發的。
BASH:是GNU的Bourne Again Shell,是GNU作業系統上預設的shell。
Korn Shell:是對Bourne SHell的發展,在大部分内容上與Bourne Shell相容。
C Shell:是SUN公司Shell的BSD版本。
Z Shell:The last shell you’ll ever need! Z是最後一個字母,也就是終極Shell。它內建了bash、ksh的重要特性,同時又增加了自己獨有的特性.
我們在系統上常用的shell是 bash
既然是程式設計,那麼程式設計所常有的概念,在shell中的展現是怎樣的呢?
事實上程式設計中所用到的變量,函數,數組,字元串,條件判斷, 循環結構在shell中都能展現.
shell腳本文法
第一行必須頂格寫并指明以下所使用的shell
#!/bin/bash
#!/usr/bin/python
#!/bin/tcsh
各種shell 如bash,python,tcsh任君選擇使用.
定義變量
shell語言是非類型的解釋型語言,強類型語言程式設計時需要事先聲明變量,并聲明其類型 shell程式設計中給一個變量指派就是定義變量.
shell的變量是無類型的,是以使用者想讓它當字元時就是字元,想讓它當數字就是數字。
當然,我們還可以用 declare來指定其資料類型
declare
-r 隻讀變量 =>相當于其它語言的常量吧,指派後不能修改
-a 數組
-i 整型
-f 函數
在linux支援的所有shell中,都可以用指派符号(=)為變量指派. 如:
abc=7 (不能在等号兩側留下空格 )
name=abc
在變量指派之後,隻需在變量前面加一個$去引用.
echo $abc
7
echo $name
abc
聲明隻讀變量方法一
[robert@ca2 CA]$ declare -r nb=100
[robert@ca2 CA]$ nb=101
-bash: na: readonly variable =>當嘗試改變隻讀變量的時候,系統會發出警告,提醒這是隻讀變量
聲明隻讀變量之方法二 将變量變成常量[隻讀變量]
[robert@ca2 CA]$ readonly na=100
[robert@ca2 CA]$ echo $na
100
[robert@ca2 CA]$ na=20
shell腳本之條件判斷
有if語句作為條件選擇分支
文法 if 條件判斷;then
執行語句
elif 條件判斷;then
fi if條件判斷結束符
有case作為條件選擇分支
switch=6
case $switch in
[0-9])
echo $switch
;;
[a-z])
esac
說到if語句結構,就得提及到條件測試
指令執行作為條件測試依據
如grep 'root' /etc/passwd 将運作指令成功與否作為判斷條件
if grep 'root' /etc/passwd;then
echo "root 使用者存在"
else
echo "root 使用者不存在"
fi
shell腳本之 case選擇分支
比較運算:
>, <, >=, <=, ==, !=
條件判斷中,存在各種判斷, 各種測試類型如下
測試類型:根據比較時的操作數的類型
整型測試:整數比較
字元測試:字元串比較
檔案測試:判斷檔案的存在性及屬性等
注意:比較運算通常隻在同一種類型間進行
整型測試:
-gt: 例如 [ $num1 -gt $num2 ]
-lt:
-ge:
-le:
-eq:
-ne:
字元串測試:
雙目
>: [[ "$str1" > "$str2" ]]
<:
>=
<=
==
!=
單目:
-n String: 是否不空,不空則為真,空則為假
-z String: 是否為空,空則為真,不空則假
bash條件測試之檔案測試:
-a file
True if file exists.
-b file
True if file exists and is a block special file.
-c file
True if file exists and is a character special file.
-d file
True if file exists and is a directory.
-e file
-f file
True if file exists and is a regular file.
-g file
True if file exists and is set-group-id.
-h file
True if file exists and is a symbolic link.
-k file
True if file exists and its ''sticky'' bit is set.
-p file
True if file exists and is a named pipe (FIFO).
-r file
True if file exists and is readable.
-s file
True if file exists and has a size greater than zero.
-t fd True if file descriptor fd is open and refers to a terminal.
-u file
True if file exists and its set-user-id bit is set.
-w file
True if file exists and is writable.
-x file
True if file exists and is executable.
-O file
True if file exists and is owned by the effective user id.
-G file
True if file exists and is owned by the effective group id.
-L file
-S file
True if file exists and is a socket.
-N file
True if file exists and has been modified since it was last read.
file1 -nt file2
True if file1 is newer (according to modification date) than file2, or if file1 exists and file2 does not.
file1 -ot file2
True if file1 is older than file2, or if file2 exists and file1 does not.
file1 -ef file2
True if file1 and file2 refer to the same device and inode numbers.
-o optname
True if shell option optname is enabled. See the list of options under the description of the -o option to the set builtin
below.
-a FILE
-e FILE: 存在則為真;否則則為假;
-f FILE: 存在并且為普通檔案,則為真;否則為假;
-d FILE: 存在并且為目錄檔案,則為真;否則為假;
-L/-h FILE: 存在并且為符号連結檔案,則為真;否則為假;
-b: 塊裝置
-c: 字元裝置
-S: 套接字檔案
-p: 命名管道
-s FILE: 存在并且為非空檔案則為值,否則為假;
-r FILE
-w FILE
-x FILE
file1 -nt file2: file1的mtime新于file2則為真,否則為假;
file1 -ot file2:file1的mtime舊于file2則為真,否則為假;
shell腳本之for in 循環
格式 for 變量 in 集合;do 語句體 ; done 循環結束辨別
詳細案例如下
declare -i sum=0
for i in {1..9};do
let sum+=$i //sum=$[$sum+$i] 中括号相加
done
echo $sum
let計算
shell腳本之for 循環
#!/bin/bash
for ((i=0;$i<10;i++));do
echo $i
done
shell腳本之while 循環
num=0
while true ;do
let num++
if [ $num -gt 10 ];then
break
fi
echo $num
shell腳本之until 循環 ==>與while循環不同的是,until的條件判斷中,條件不成立,循環會繼續進行
until [ $num -gt 10 ];do
shell 腳本之函數使用
function test {
echo "$1 do you want test function"
}
test 'robert'
shell腳本之數組
數組是程式設計中,存儲控制資料非常重要的一個手段和方式,但遺憾的是 linux的shell隻支援一維數組
數組其實也是一種變量,不同的是,這個特殊類型的變量内,還可以存其它的變量.
數組的使用
數組名+索引
數組元素
索引的表示方式:
數字索引:a[index]
a[0], a[1]
bash 4.0的關聯數組
a[hello], a[hi]
declare -a 索引數組
-A 關聯數組
支援稀疏格式:
數組的指派:
一次對一個元素指派:
a[0]=0
a[1]=1
a[2]=2
a[3]=3
直接指派:
arr=(0 1 2 3)
按索引進行指派:
a=([0]=0 [3]=3 [2]=2 [1]=1)
使用者輸入:
read -a arr 使用者輸入的方式生成數組
數組的通路:
用索引通路:
ARRAY[index]
如 a=([0]=0 [3]=3 [2]=2 [1]=1)
echo a[0]通路索引為0的數組
0 ==>結果為0
數組的長度:
[robert@ca2 ~]$ array=([0]=0 [3]=3 [2]=2 [1]=1)
[robert@ca2 ~]$ echo ${#array[@]}
4
從數組中挑選某元素:
${ARRAY[@]:offset:number}
切片:
offset: 偏移的元素個數
number: 取出的元素的個數
[robert@ca2 ~]$ echo ${array[@]:1:2}
1 2
${ARRAY[@]:offset}:取出偏移量後的所有元素
[robert@ca2 ~]$ echo ${array[@]:1}
1 2 3
${ARRAY[@]}: 取出所有元素
[robert@ca2 ~]$ echo ${array[@]}
0 1 2 3
使用@和*的不同
$@: 每個參數是一個獨立的串
$*: 所有參數是一個串
數組如果想作為對數傳入給函數使用,怎麼辦呢?
#!/bin/bash
function myarr {
#echo $@
#exit 0
newarr=(echo "$@") 接收時轉化為數組
echo ${newarr[@]}
myarray=(12 23 34 45)
myarr ${myarray[@]} ==>注,為函數傳遞數組作為變量,需要注意,要将其轉化為N個參數傳入
在程式設計中,字元串的操作是相當頻繁常用的
字元串
字元串切片:
${string:offset:length} 從左向右取,依稀量,加長度, 如果隻指定偏移量,則偏移後,取所有字串
取尾部的指定個數的字元:
${string: -length} 加個 " - " 号,則是從右向左取
取子串:基于模式
${variable#*word}:在variable中存儲字串上,自左而右,查找第一次出現word,删除字元開始至此word處的所有内容;
[root@localhost ~]# url=www.baidu.com
[root@localhost ~]# echo $url
www.baidu.com
[root@localhost ~]# echo ${url#*.} 從左到右,取第一次出現的.号,并從左開始第一個字元删除到第一次出現的字元,
baidu.com
[root@localhost ~]# echo ${url##*.} 再加一個# 是貪婪模式,找到從左到右,最後一次出現的 . 并從頭到 . 删除
com
${variable##*word}:在variable中存儲字串上,自左而右,查找最後一次出現word,删除字元開始至此word處的所有内容;
file='/var/log/messages'
${file#*/}: 傳回的結果是var/log/messages
${file##*/}: 傳回messages
${variable%word*}: 在variable中存儲字串上,自右而左,查找第一次出現word,删除此word處至字串尾部的所有内容;
${variable%%world*}:在variable中存儲字串上,自右而左,查找最後一次出現word,删除此word處至字串尾部的所有内容;
${file%*/}: 傳回的結果是/var/log
${file%%*/}: 傳回結果為空
phonenumber='010-110-8'
${phonenumber%%-*}
${phonenumber##*-}
url="http://www.magedu.com:80"
周遊通路一個字元串(預設是以空格分開的,當字元串是由其他字元分隔時可以參考 2)
str="a --m"
for i in $str
do
echo $i
array
聲明數組 myarray=(1 2 3 )
列印數組 echo ${myarray[@]}
通路數組的長度 ${#myarray[@]}
[root@localhost ~]# echo ${#myarray[@]}
3
#直接輸出的是數組的第一個元素
echo $array
#用下标的方式通路數組元素
echo ${array[1]}
#輸出這個數組
echo ${array[@]}
#輸出數組中下标為3的元素的長度
echo ${#array[3]}
#輸出數組中下标 為1到3的元素
echo ${array[@]:1:3}
#輸出數組中下标大于2的元素
echo ${array[@]:2}
#輸出數組中下标小于2的元素
echo ${array[@]::2}
${string:offset:length} 從左向右取,依稀量,加長度, 如果隻指定偏移量,則偏移後,取所有字串
${string: -length} 加個 " - " 号,則是從右向左取
${variable#*word}:在variable中存儲字串上,自左而右,查找第一次出現word,删除字元開始至此word處的所有内容;
${file##*/}: 傳回messages
${file%%*/}: 傳回結果為空
${phonenumber##*-}
url="http://www.magedu.com:80"
1.長度
[root@localhost ~]$ test='I love china'
[root@localhost ~]$ echo ${#test}
12
${#變量名}得到字元串長度
2.截取字串
[root@localhost ~]$ test='I love china'
[root@localhost ~]$ echo ${test:5}
e china
[root@localhost ~]$ echo ${test:5:10}
${變量名:起始:長度}得到子字元串
3.字元串删除
[root@localhost ~]$ test='//tmp/boot.ini'
[root@localhost ~]$ echo ${test#/}
/tmp/boot.ini
[root@localhost ~]$ echo ${test#*/}
[root@localhost ~]$ echo ${test##*/}
boot.ini
[root@localhost ~]$ echo ${test%/*}
c:/windows
[root@localhost ~]$ echo ${test%%/*}
${變量名#substring正規表達式}從字元串開頭開始配備substring,删除比對上的表達式。
${變量名%substring正規表達式}從字元串結尾開始配備substring,删除比對上的表達式。
注意:${test##*/},${test%/*} 分别是得到檔案名,或者目錄位址最簡單方法。
4.字元串替換
[chengmo@localhost ~]$ test='/tmp/boot.ini'
[chengmo@localhost ~]$ echo ${test/\//\\}
[chengmo@localhost ~]$ echo ${test//\//\\}