Linux_(3)Shell編程(上)
一、shell 簡介
Shell 是一個用 C 語言編寫的程序,它是用戶使用 Linux 的橋梁。
Shell 既是一種命令語言,又是一種程序設計語言。
Shell 是指一種應用程序,這個應用程序提供了一個界面,用戶通過這個界面訪問操作系統內核的服務。
1.Shell 腳本
Shell 腳本(shell script),是一種為 shell 編寫的腳本程序。
什麽是腳本語言?
腳本語言是像劇本一樣教計算機辦某個事情的語言,
這類程序可以用文本編輯器修改,不需要編譯,通常是解釋運行的。
2.Shell 環境
Linux 的 Shell 種類眾多,常見的有:
Bourne Shell(/usr/bin/sh或/bin/sh)
C Shell(/usr/bin/csh)
K Shell(/usr/bin/ksh)
Shell for Root(/sbin/sh)
……
Bash(Bourne Again Shell)是日常工作中使用最廣泛的,也是大多數Linux 系統默認的 Shell。
在一般情況下,並不區分 Bourne Shell 和 Bourne Again Shell,
所以,像 #!/bin/sh,它同樣也可以改為 #!/bin/bash。
#! 告訴系統其後路徑所指定的程序即是解釋此腳本文件的 Shell 程序。
3.第一個shell腳本
打開文本編輯器(可以使用 vi/vim 命令來創建文件),
cat > hello.sh <<!
實例
#!/bin/bash
echo "Hello World !"
#! 是一個約定的標記,它告訴系統這個腳本需要什麽解釋器來執行,即使用哪一種 Shell。
echo 命令用於向窗口輸出文本。
4.運行 Shell 腳本有兩種方法:
4.1 作為可執行程序
將上面的代碼保存為 hello.sh,並 cd 到相應目錄:
chmod u+x ./hello.sh #使腳本具有執行權限
./hello.sh #執行腳本
註意,一定要寫成 ./hello.sh,而不是 hello.sh,運行其它二進制的程序也一樣,
而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 裏,
當前目錄通常不在 PATH 裏,所以寫成 hello.sh 是會找不到命令的,
要用 ./hello.sh 告訴系統說,就在當前目錄找。
4.2 作為解釋器參數
這種運行方式是,直接運行解釋器,其參數就是 shell 腳本的文件名,如:
/bin/sh hello.sh
這種方式運行的腳本,不需要在第一行指定解釋器信息,寫了也沒用。
二、shell變量
1.定義變量
your_name="lw"
註意:變量名和等號之間不能有空格。
變量名的命名須遵循如下規則:
首個字符必須為字母(a-z,A-Z)。
中間不能有空格,可以使用下劃線(_)。
不能使用標點符號。
不能使用bash裏的關鍵字(可用help命令查看保留關鍵字)。
2.使用變量
使用一個定義過的變量,只要在變量名前面加美元符號即可,如:
your_name="lw"
echo $your_name
例子:
cat > your_name.sh <<!
#!/bin/bash
your_name="lw"
echo $your_name
chmod u+x ./your_name.sh #使腳本具有執行權限
./your_name.sh #執行腳本
變量名外面的花括號是可選的,加不加都行,加花括號是為了幫助解釋器識別變量的邊界.
echo ${your_name}
已定義的變量,可以被重新使用:
#!/bin/bash
your_name="lw"
echo ${your_name}
your_name="alibaba"
echo ${your_name}
3.只讀變量
使用 readonly 命令可以將變量定義為只讀變量,只讀變量的值不能被改變。
嘗試更改只讀變量,結果報錯:your_name: 只讀變量
#!/bin/bash
your_name="lw"
echo ${your_name}
readonly your_name
your_name="alibaba"
echo ${your_name}
4.刪除變量
使用 unset 命令可以刪除變量。語法:
unset variable_name
變量被刪除後不能再次使用。unset 命令不能刪除只讀變量。
#!/bin/bash
your_name="lw"
echo ${your_name}
#readonly your_name
unset your_name
echo ${your_name}
5.變量類型
運行shell時,會同時存在三種變量:
5.1 局部變量
局部變量在腳本或命令中定義,僅在當前shell實例中有效,
其他shell啟動的程序不能訪問局部變量。
5.2 環境變量
所有的程序,包括shell啟動的程序,都能訪問環境變量,
有些程序需要環境變量來保證其正常運行。
必要的時候shell腳本也可以定義環境變量。
5.3 shell變量
shell變量是由shell程序設置的特殊變量。
shell變量中有一部分是環境變量,有一部分是局部變量,
這些變量保證了shell的正常運行
6.Shell 字符串
字符串是shell編程中最常用最有用的數據類型(數字和字符串),
字符串可以用單引號,也可以用雙引號,也可以不用引號。
6.1 單引號
your_name=‘lw‘
單引號字符串的限制:
單引號裏的任何字符都會原樣輸出,
單引號字符串中的變量是無效的;
單引號字串中不能出現單引號(對單引號使用轉義符後也不行)。
6.2 雙引號
雙引號的優點:
雙引號裏可以有變量
雙引號裏可以出現轉義字符
cat > your_name3.sh <<!
#!/bin/bash
your_name=‘lw‘
echo "hello,${your_name}!"
#echo "Hello, \"$your_name\"! \n"
6.3 拼接字符串
6.4 # 獲取字符串長度
cp your_name3.sh your_name4.sh
#!/bin/bash
your_name="lw"
string=hello
echo $string $your_name
echo ${#string}
echo ${#your_name}
6.5 : 提取子字符串
從字符串第 2 個字符開始截取 4 個字符:
#!/bin/bash
string="hello lw!"
echo ${string:1:4} # 輸出 ello
6.6 查找子字符串
查找字符 "e" 的位置:
#!/bin/bash
string="hello lw!"
echo `expr index "$string" e` # 輸出 2
註意: 以上腳本中 "`" 是反引號,而不是單引號 "‘".
cp your_name4.sh your_name5.sh
vi your_name5.sh
#!/bin/bash
string="hello lw!"
echo ${string:1:4}
echo `expr index "$string" e`
7.Shell 註釋
以"#"開頭的行就是註釋,會被解釋器忽略。
每一行加一個#號可以註釋一行;
sh裏沒有多行註釋,可以把這一段要註釋的代碼用一對花括號括起來,
定義成一個函數,沒有地方調用這個函數,這塊代碼就不會執行,達到了和註釋一樣的效果。
8.字符串截取的八種方法:
假設有變量 var=http://www.aaa.com/123.htm
8.1 從左邊第幾個字符開始,及字符的個數
echo ${var:0:5}
其中的 0 表示左邊第一個字符開始,5 表示字符的總個數。
結果是:http:
8.2 從左邊第幾個字符開始,一直到結束。
echo ${var:7}
其中的 7 表示左邊第8個字符開始,一直到結束。
結果是 :www.aaa.com/123.htm
8.3 從右邊第幾個字符開始,及字符的個數
echo ${var:0-7:3}
其中的 0-7 表示右邊算起第七個字符開始,3 表示字符的個數。
結果是:123
8.4 從右邊第幾個字符開始,一直到結束。
echo ${var:0-7}
表示從右邊第七個字符開始,一直到結束。
結果是:123.htm
註:(左邊的第一個字符是用 0 表示,右邊的第一個字符用 0-1 表示)
#、## 表示從左邊開始刪除。
一個 # 表示從左邊刪除到第一個指定的字符;
兩個 # 表示從左邊刪除到最後一個指定的字符。
%、%% 表示從右邊開始刪除。
一個 % 表示從右邊刪除到第一個指定的字符;
兩個 % 表示從右邊刪除到最後一個指定的字符。
刪除包括了指定的字符本身。
8.5 # 號截取,刪除左邊字符,保留右邊字符。
echo ${var#*//}
其中 var 是變量名,# 號是運算符,*// 表示從左邊開始刪除第一個 // 號及左邊的所有字符
即刪除 http://
echo ${var#*/}
結果是 :/www.aaa.com/123.htm
8.6 ## 號截取,刪除左邊字符,保留右邊字符。
echo ${var##*/}
##*/ 表示從左邊開始刪除最後(最右邊)一個 / 號及左邊的所有字符
即刪除 http://www.aaa.com/
結果是 123.htm
8.7 %號截取,刪除右邊字符,保留左邊字符
echo ${var%/*}
%/* 表示從右邊開始,刪除第一個 / 號及右邊的字符
結果是:http://www.aaa.com
8.8 %% 號截取,刪除右邊字符,保留左邊字符
echo ${var%%/*}
%%/* 表示從右邊開始,刪除最後(最左邊)一個 / 號及右邊的字符
結果是:http:
三、shell傳遞參數
1.傳遞參數
在執行 Shell 腳本時,向腳本傳遞參數,腳本內獲取參數的格式為:$n。
n 代表一個數字,1 為執行腳本的第一個參數,2 為執行腳本的第二個參數,以此類推……
cp your_name.sh parameter.sh
#!/bin/bash
echo "hello $1";
調用: ./parameter.sh lw
2.參數處理
$# 傳遞到腳本的參數個數
$* 以一個單字符串顯示所有向腳本傳遞的參數,以"$1 $2 … $n"的形式輸出所有參數。
$@ 與$*相同,但是使用時加引號(如"$@"),並在引號中返回每個參數"$1“ ”$2“ … ”$n"。
$* 與 $@ 區別:
相同點:都是引用所有參數。
不同點:只有在雙引號中體現出來。
假設在腳本運行時寫了三個參數 1、2、3,,
則 " * " 等價於 "1 2 3"(傳遞了一個參數),
而 "@" 等價於 "1" "2" "3"(傳遞了三個參數)。
cp prameter.sh prameter2.sh
#!/bin/bash
echo "$1";
echo "$2";
echo "$#";
echo $*;
for i in "$*"; do
echo $i
done
echo "$@";
for i in "$@"; do
echo $i
done
調用: ./prameter2.sh lw 1123 null
四、shell 運算符
shell運算符分為6類,包括:
算術運算符
關系運算符
布爾運算符
邏輯運算符
字符串運算符
文件測試運算符
原生bash不支持簡單的數學運算,但是可以通過expr命令來實現。
expr 是一款表達式計算工具,使用它能完成表達式的求值操作。
例如,兩個數相加(註意使用的是反引號 ` 而不是單引號 ‘):
#!/bin/bash
val=`expr 2 + 2`
echo "兩數之和為 : $val"
兩點註意:
表達式和運算符之間要有空格,例如 2+2 是不對的,必須寫成 2 + 2。
完整的表達式要被 ` ` 包含,註意這個字符不是常用的單引號,在 Esc 鍵下邊。
1.算術運算符
下表列出了常用的算術運算符,假定變量 a 為 10,變量 b 為 20:
+ 加法 `expr $a + $b` 結果為 30。
- 減法 `expr $a - $b` 結果為 -10。
* 乘法 `expr $a \* $b` 結果為 200。 乘號(*)前邊必須加反斜杠(\)才能實現乘法運算
/ 除法 `expr $b / $a` 結果為 2。
% 取余 `expr $b % $a` 結果為 0。
在 MAC 中 shell 的 expr 語法是:$((表達式)),此處表達式中的 "*" 不需要轉義符號 "\" 。
= 賦值 a=$b 將把變量 b 的值賦給 a。
== 相等。 用於比較兩個數字,相同則返回 true。 [ $a == $b ] 返回 false。
!= 不相等。 用於比較兩個數字,不相同則返回 true。 [ $a != $b ] 返回 true。
註意:條件表達式要放在方括號之間,並且要有空格,
例如: [$a==$b] 是錯誤的,必須寫成 [ $a == $b ]。
算術運算符實例如下:
#!/bin/bash
a=10;
b=20;
val=`expr $a + $b`;
echo "a + b : $val";
val=`expr $a - $b`;
echo "a - b : $val";
val=`expr $a \* $b`;
echo "a * b : $val";
val=`expr $b / $a`;
echo "b / a : $val";
val=`expr $b % $a`;
echo "b % a : $val";
if [ $a == $b ]
then
echo "a 等於 b";
elfi [ $a != $b ]
then
echo "a 不等於 b"
fi
#!/bin/bash
a=10;
b=20;
echo "a+b= $((a+b))";
echo "a-b= $((a-b))";
echo "a*b= $((a*b))";
echo "b/a= $((b/a))";
echo "a%3= $((a%3))";
2.關系運算符
關系運算符只支持數字,不支持字符串,除非字符串的值是數字。
下表列出了常用的關系運算符,假定變量 a 為 10,變量 b 為 20:
-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。
eq 就是 equal等於
ne 就是 not equal不等於
gt 就是 greater than大於
lt 就是 less than小於
ge 就是 greater than or equal 大於等於
le 就是 less than or equal 小於等於
關系運算符實例如下:
#!/bin/bash
a=10;
b=20;
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等於 b"
else
echo "$a -eq $b: a 不等於 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等於 b"
else
echo "$a -ne $b : a 等於 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大於 b"
else
echo "$a -gt $b: a 不大於 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小於 b"
else
echo "$a -lt $b: a 不小於 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大於或等於 b"
else
echo "$a -ge $b: a 小於 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小於或等於 b"
else
echo "$a -le $b: a 大於 b"
fi
3.布爾運算符
下表列出了常用的布爾運算符,假定變量 a 為 10,變量 b 為 20:
! 非運算,表達式為 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。
布爾運算符實例如下:
#!/bin/bash
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等於 b"
else
echo "$a != $b: a 等於 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小於 100 且 $b 大於 15 : 返回 true"
else
echo "$a 小於 100 且 $b 大於 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小於 100 或 $b 大於 100 : 返回 true"
else
echo "$a 小於 100 或 $b 大於 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小於 5 或 $b 大於 100 : 返回 true"
else
echo "$a 小於 5 或 $b 大於 100 : 返回 false"
fi
4.邏輯運算符
以下介紹 Shell 的邏輯運算符,假定變量 a 為 10,變量 b 為 20:
&& 邏輯的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 邏輯的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true
邏輯運算符實例如下:
#!/bin/bash
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
5.字符串運算符
下表列出了常用的字符串運算符,假定變量 a 為 "abc",變量 b 為 "efg":
= 檢測兩個字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。
!= 檢測兩個字符串是否不相等,不相等返回 true。 [ $a != $b ] 返回 true。
-z 檢測字符串長度是否為0,為0返回 true。 [ -z $a ] 返回 false。
-n 檢測字符串長度是否不為0,不為0返回 true。 [ -n $a ] 返回 true。
str 檢測字符串是否不為空,不為空返回 true。 [ $a ] 返回 true。
字符串運算符實例如下:
#!/bin/bash
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
6.文件測試運算符
文件測試運算符用於檢測 Unix 文件的各種屬性。
屬性檢測描述如下:
-b file 檢測文件是否是塊設備文件,如果是,則返回 true。 [ -b $file ] 返回 false。
-c file 檢測文件是否是字符設備文件,如果是,則返回 true。 [ -c $file ] 返回 false。
-d file 檢測文件是否是目錄,如果是,則返回 true。 [ -d $file ] 返回 false。
-f file 檢測文件是否是普通文件(既不是目錄,也不是設備文件),如果是,則返回 true。 [ -f $file ] 返回 true。
-p file 檢測文件是否是有名管道,如果是,則返回 true。 [ -p $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。
-g file 檢測文件是否設置了 SGID 位,如果是,則返回 true。 [ -g $file ] 返回 false。
-k file 檢測文件是否設置了粘著位(Sticky Bit),如果是,則返回 true。 [ -k $file ] 返回 false。
-u file 檢測文件是否設置了 SUID 位,如果是,則返回 true。 [ -u $file ] 返回 false。
變量 file 表示文件"/var/www/a.txt",具有 rwx 權限。
下面的代碼,將檢測該文件的各種屬性:
#!/bin/bash
file="/home/lw/a.txt"
if [ -r $file ]
then
echo "文件可讀"
else
echo "文件不可讀"
fi
if [ -w $file ]
then
echo "文件可寫"
else
echo "文件不可寫"
fi
if [ -x $file ]
then
echo "文件可執行"
else
echo "文件不可執行"
fi
if [ -f $file ]
then
echo "文件為普通文件"
else
echo "文件為特殊文件"
fi
if [ -d $file ]
then
echo "文件是個目錄"
else
echo "文件不是個目錄"
fi
if [ -s $file ]
then
echo "文件不為空"
else
echo "文件為空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
Linux_(3)Shell編程(上)