Shell簡介 Shell 是一個用 C 語言編寫的程式,它是用戶使用 Linux 的橋梁。Shell 既是一種命令語言,又是一種程式設計語言。 Shell 是指一種應用程式,這個應用程式提供了一個界面,用戶通過這個界面訪問操作系統內核的服務。 Ken Thompson 的 sh 是第一種 Unix ...
Shell簡介
Shell 是一個用 C 語言編寫的程式,它是用戶使用 Linux 的橋梁。Shell 既是一種命令語言,又是一種程式設計語言。
Shell 是指一種應用程式,這個應用程式提供了一個界面,用戶通過這個界面訪問操作系統內核的服務。
Ken Thompson 的 sh 是第一種 Unix Shell,Windows Explorer 是一個典型的圖形界面 Shell。
Shell運行原理
Linux嚴格意義上是一個操作系統,我們稱為核心,但我們一般的用戶是不能直接使用核心的,而是通過外殼程式。也就是shell,對比Windows,圖形界面就是外殼程式。shell的簡單定義就是命令行解釋器,功能是將使用者的命令翻譯給核心處理,同時將核心處理的結果翻譯給使用者。可以看出shell主要是對我們的指令進行解析,解析指令給Linux內核。反饋結果在通過內核運行出結果,通過shell解析給用戶。
shell在解釋命令的時候並不是自己親自執行,而是派生子進程讓子進程去完成這項工作,這樣的好處是把風險交給別人,當指令的執行出現問題時不會影響到shell(影響到其他指令的執行)。shell不可以掛,shell 一旦掛就沒有什麼可以解釋命令了。對我們而言shell為了保證自己風險最低,通過創建子進程進行命令行的解釋工作。而shell自己只要去等就可以了。
Shell 腳本
Shell 腳本(shell script),是一種為 shell 編寫的腳本程式。 業界所說的 shell 通常都是指 shell 腳本,但讀者朋友要知道,shell 和 shell script 是兩個不同的概念。
Shell腳本解釋器
Linux的Shell腳本解釋器種類眾多,一個系統可以存在多個shell腳本解釋器,可以通過cat /etc/shells
命令查看系統中安裝的shell腳本解釋器。
/bin/sh
/bin/bash
/bin/rbash
bash由於易用和免費,在日常工作中被廣泛使用。同時,Bash也是大多數Linux系統預設的Shell腳本解釋器。
shell腳本頭,#!/bin/sh與#!/bin/bash的區別.
GNU/Linux操作系統中的/bin/sh本是bash (Bourne-Again Shell)的符號鏈接,但鑒於bash過於複雜,有人把bash從NetBSD移植到Linux並更名為dash Debian Almquist Shell),並建議將/bin/sh指向它(軟鏈),以獲得更快的腳本執行速度。Dash Shell 比Bash Shell小的多,符合POSIX標準。
sh一般設成bash的軟鏈
在一般的linux系統當中(如redhat),使用sh調用執行腳本相當於打開了bash的POSIX標準模式
也就是說 /bin/sh 相當於 /bin/bash --posix
sh跟bash的區別,實際上就是bash有沒有開啟posix模式的區別
第一個shell腳本
新建一個文件 test.sh,擴展名為 sh(sh代表shell),擴展名並不影響腳本執行,見名知意就好。
運行 Shell 腳本有兩種方法:
1、作為可執行程式
cd 到相應目錄:
chmod +x ./test.sh #使腳本具有執行許可權 ./test.sh #執行腳本
註意,一定要寫成 ./test.sh,而不是 test.sh,運行其它二進位的程式也一樣,直接寫 test.sh,linux 系統會去 PATH 里尋找有沒有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的當前目錄通常不在 PATH 里,所以寫成 test.sh 是會找不到命令的,要用 ./test.sh 告訴系統說,就在當前目錄找。
2、作為解釋器參數
這種運行方式是,直接運行解釋器,其參數就是 shell 腳本的文件名,如:
/bin/sh test.sh
Shell變數
語法規則:變數名=變數值 my_name="Gavin Pan"
註意,變數名和等號之間不能有空格,這可能和你熟悉的所有編程語言都不一樣。同時,變數名的命名規則與其他語言差不多,不能使用bash里的關鍵字(可用help命令查看保留關鍵字)。
1.變數類型
局部變數:局部變數在腳本或命令中定義,僅在當前shell實例中有效,其他shell啟動的程式不能訪問局部變數。
環境變數:所有的程式,包括shell啟動的程式,都能訪問環境變數,有些程 序需要環境變數來保證其正常運行。可以用過set命令查看當前環境變數。
shell變數:由shell程式設置的特殊變數。shell變數中有一部分是環境變數,有一部分是局部變數,這些變數保證了shell 的正常運行。
2.定義變數
my_name="Gavin Pan"
3.引用變數
echo $my_name
echo ${my_name}
#引用一個定義過的變數,只要在變數名前面加$即可,變數名外面的花括弧是可選的,加不加都行,加花括弧是為了幫助解釋器識別變數的邊界。
4.重新定義變數
my_name = "Gavin"
my_name="Gavin Pan"
5.只讀變數
使用readonly 命令將變數變成只讀變數
my_name = "Gavin"
readonly my_name
my_name="Gavin Pan"
6.刪除變數
my_name="Gavin"
unset my_name
echo $my_name
使用unset命令可以刪除變數,變數被刪除後不能再次使用,同時unset命令不能刪除只讀變數。
Shell字元串
字元串是shell編程中最常用最有用的數據類型(除了數字和字元串,也沒啥其它類型好用了),字元串可以用單引號,也可以用雙引號,也可以不用引號。單雙引號的區別跟PHP類似。
str1='hello Gavin'
str2="hello Gavin"
str3="hello \"$my_name\"
echo str1 #hello Gavin
echo str2 #hello Gavin
echo str3 #hello "Gavin Pan"
雙引號的優點:可以有變數,可以轉義字元。
字元串相關操作
#拼接字元串
a="a"
b="b"
c=$a$b 或者 c="$a $b"
獲取字元串長度
str="abcdefg"
echo ${#str} #output 7
提取字元串
echo ${str:1:3} #output bcd
以上例子表示從字元串的第二個數字往後截取3個字元
查找字元串
echo `expr index "$str" cb` #output 2
註意: 以上腳本中 ` 是反引號,而不是單引號 ',不要看錯了哦。
查找字元 c 或 b 的位置(哪個字母先出現就計算哪個)
shell 數組
在 Shell 中,用括弧來表示數組,數組元素用"空格"符號分割開。定義數組的一般形式為: 數組名=(值1 值2 ... 值n) 例如:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
還可以單獨定義數組的各個分量:
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
可以不使用連續的下標,而且下標的範圍沒有限制。 讀取數組 讀取數組元素值的一般格式是: ${數組名[下標]} 例如:
valuen=${array_name[n]}
使用 @ 符號可以獲取數組中的所有元素,例如:
echo ${array_name[@]}
獲取數組的長度
獲取數組長度的方法與獲取字元串長度的方法相同,例如:
取得數組元素的個數
length=${#array_name[@]}
或者
length=${#array_name[*]}
取得數組單個元素的長度
lengthn=${#array_name[n]}
shell參數傳遞
echo "Shell 傳遞參數實例!";
echo "執行的文件名:$0";
echo "第一個參數為:$1";
echo "第二個參數為:$2";
echo "第三個參數為:$3";
執行結果如下
$ chmod +x test.sh
$ ./test.sh 1 2 3
Shell 傳遞參數實例!
執行的文件名:./test.sh
第一個參數為:1
第二個參數為:2
第三個參數為:3
shell特殊字元
$# 傳遞到腳本的參數個數 $* 以一個單字元串顯示所有向腳本傳遞的參數 $$ 腳本運行的當前進程ID號 $! 後臺運行的最後一個進程的ID號 $@ 與$*相同,但是使用時加引號,併在引號中返回每個參數 $? 顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤
$*和$@區別: 相同點:都表示傳遞給腳本的所有參數。 不同點:不被” “包含時,$和$@都以$1 $2… $n 的形式組成參數列表。 被” “包含時,”$” 會將所有的參數作為一個整體,以”$1 $2 … $n” 的形式組成一個整串;”$@” 會將各個參數分開,以”$1” “$2” … “$n” 的 形式組成一個參數列表。
shell 基本運算符
算數運算符
原生bash不支持簡單的數學運算,但是可以通過其他命令來實現,例如 awk 和 expr,expr 最常用。
expr 是一款表達式計算工具,使用它能完成表達式的求值操作。
a=1
b=2
val=`expr $a + $b`
需要註意的是運算符左右要有空格,特殊記住乘號前面要叫\,其他的沒什麼區別。
關係運算符
關係運算符只支持數字,不支持字元串,除非字元串的值是數字。
-eq 檢測兩個數是否相等,相等返回 true。 [ $a -eq $b ] 返回 false。 -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。
布爾運算符
! 非運算,表達式為 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。
邏輯運算符
&& 邏輯的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false || 邏輯的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
字元串運算符
= 檢測兩個字元串是否相等,相等返回 true。 [ $a = $b ] 返回 false。 != 檢測兩個字元串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。 -z 檢測字元串長度是否為0,為0返回 true。 [ -z $a ] 返回 false。 -n 檢測字元串長度是否為0,不為0返回 true。 [ -n "$a" ] 返回 true。 $ 檢測字元串是否為空,不為空返回 true。 [ $a ] 返回 true。
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a 等於 b"
else
echo "$a = $b: a 不等於 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等於 b"
else
echo "$a != $b: a 等於 b"
fi
if [ -z $a ]
then
echo "-z $a : 字元串長度為 0"
else
echo "-z $a : 字元串長度不為 0"
fi
if [ -n "$a" ]
then
echo "-n $a : 字元串長度不為 0"
else
echo "-n $a : 字元串長度為 0"
fi
if [ $a ]
then
echo "$a : 字元串不為空"
else
echo "$a : 字元串為空"
fi
執行腳本,輸出結果如下所示:
abc = efg: a 不等於 b
abc != efg : a 不等於 b
-z abc : 字元串長度不為 0
-n abc : 字元串長度不為 0
abc : 字元串不為空
文件測試運算符
-b file 檢測文件是否是塊設備文件,如果是,則返回 true。 [ -b $file ] 返回 false。 -c file 檢測文件是否是字元設備文件,如果是,則返回 true。 [ -c $file ] 返回 false。 -d file 檢測文件是否是目錄,如果是,則返回 true。 [ -d $file ] 返回 false。 -f file 檢測文件是否是普通文件(既不是目錄,也不是設備文件),如果是,則返回 true。 [ -f $file ] 返回 true。 -g file 檢測文件是否設置了 SGID 位,如果是,則返回 true。 [ -g $file ] 返回 false。 -k file 檢測文件是否設置了粘著位(Sticky Bit),如果是,則返回 true。 [ -k $file ] 返回 false。 -p file 檢測文件是否是有名管道,如果是,則返回 true。 [ -p $file ] 返回 false。 -u file 檢測文件是否設置了 SUID 位,如果是,則返回 true。 [ -u $file ] 返回 false。 -r file 檢測文件是否可讀,如果是,則返回 true。 [ -r $file ] 返回 true。 -w file 檢測文件是否可寫,如果是,則返回 true。 [ -w $file ] 返回 true。 -x file 檢測文件是否可執行,如果是,則返回 true。 [ -x $file ] 返回 true。 -s file 檢測文件是否為空(文件大小是否大於0),不為空返回 true。 [ -s $file ] 返回 true。 -e file 檢測文件(包括目錄)是否存在,如果是,則返回 true。 [ -e $file ] 返回 true。
file="/test.sh"
if [ -r $file ]
shell 流程式控制制
if condition
then
command
fi
if condition
then
command
else
commandN
fi
if condition
then
command
elif confition2
then
command2
else
cpmmandN
fi
for loop in 1 2 3 4 5
do
echo $loop
done
while condition
do
command
done
until condition
do
command
done
與while正好相反
echo '輸入 1 到 4 之間的數字:'
echo '你輸入的數字為:'
read aNum
case $aNum in
1) echo '你選擇了 1'
;;
2) echo '你選擇了 2'
;;
3) echo '你選擇了 3'
;;
4) echo '你選擇了 4'
;;
*) echo '你沒有輸入 1 到 4 之間的數字'
;;
esac