1. 為什么要學習shell編程?
許多人會問,為什么要學習shell腳本編程?我學的是linux,又不是編程,其實對于個人用戶可能用處不是很大,但是當你在為公司的成千上完的服務器做維護時,可能沒有shell編程的話可能把人累死也無法完成任務,一千臺服務器要做相同的工作,總不能在一千臺服務器上敲一遍命令,況且人在做大量的無聊的工作極易犯錯。又或者你需要在晚上3點備份數據庫,你不可能晚上爬起來開電腦連接到公司服務器上去操作吧,這個寫個腳本加到crontab 完事,當你寫了shell腳本,執行一遍就能輕松解決這樣的問題。
2. shell腳本基礎:
shell腳本是包含一些命令或聲明,并符合一定格式的文本文件首行shebang機制:(聲明解釋器,否則使用當前shell的默認解釋器,為了避免發生錯誤強烈建議不要省略)一般使用#作為注釋內容,但是除了行首除外,如下為三種聲明:
#!/bin/bash #!/usr/bin/python #!/usr/bin/perl
shell腳本一般用文本編輯器創建,并給文件賦予執行權限(也可以用bash解釋器解釋執行),bash命令可以解釋腳本。
范例:
#!/bin/bash #author:jackcui #description: first bash script //描述信息 echo “hello world!” //打印hello world! 調試運行: bash -n /root/bin/first_script //檢查腳本中語法錯誤 bash -x / root/bin/first_script //調試執行
3. 變量(命令的內存空間):
(1)變量類型
字符型:數字,字母,下劃線等
數值型:整型,浮點型
(2)本地變量:對當前shell生效,對其子shell等無效
可以是直接字符串:name=”root”
變量引用:name=$USER 如果USER變量后面還有字符,要用{}括起來,$是引用變量相當于變量存放的值,給變量賦值時,前面是變量本身,后面用變量賦值時后面時用的變量的值要加$
命令引用:name`COMMAND`
注釋:引號的使用類似于正則表達式,可以使用set,unset顯示定義的所有變量
(3)環境變量:對當前shell及其子shell生效
對設置了本地變量的變量使用export或declare進行聲明
export name=root
一般可以使用export或env顯示所有的環境變量,unset取消變量的聲明
declare –x name=root
(4)局部變量:對某一斷代碼生效
(5)位置變量:用$1,$2,${10}表示用于腳本運行時傳遞給它的參數
(6)特殊變量:$?, $0, $*,$@,$#表示和參數相關的變量
4. 算術運算:
bash支持算術運算,不支持浮點運算:+ – * / % ** (加,減,乘,除,取模,乘方)乘法符號有時需要轉義
(1)let var=算術表達式 eg:let sum=3+5
(2)var=$[算術表達式] eg: $[3+5]
(3)var=$((算術表達式)) eg: $((3+5))
(4)declare –i var=5
(5)var=$(expr arg1 arg2 arg3)
(6)echo ‘算術表達式’ |bc
(7)產生隨機數:echo $ [$RANDOM%50]產生0-49之間的隨機數因為是對50取余數,random范圍(1-32767)
5. 邏輯運算:(true 1,false 0)
與:全1為1
或:有1為1
非:取反
短路與&&:第一個操作數為0,結果為0,第一操作數為1,第二操作數要運算
短路或:第一操作數為1結果為1,第一操作數為0,計算第二操作數
異或^:兩個操作數相同為假,不同為真
6. 聚集命令:
(1) ;為分割符聚集 date; who |wc –l
(2)()打開子shell,命令執行完,退出子shell。 (date;who |wc -l)>> /tmp/trace
(3){} 在當前shell執行,但是第一個括號后要加空格,最后一個命令之間要加分號
eg:
[root@centos7 ~]# { ls -l /root/bin|head -n3; ls -ld /root/bin;} total 72 -rwxr-xr-x. 1 root root 315 Aug 13 15:39 A2Bsum.sh -rwxr-xr-x. 1 root root 214 Aug 13 11:02 argsnum.sh drwxr-sr-x. 2 root root 4096 Aug 14 16:27 /root/bin
7. 增強賦值:
+= -= *= /= %= ++ —
8. 退出狀態:
0表示成功,1-255表示失敗。 eg :ll a.txt ;echo $? 可以看到上一個命令是否執行成功,可以在bash腳本自定義退出碼,根據退出碼,判斷在哪里出錯,類似于網頁404
9. 字符串測試比較:
== 是否等于,兩邊都應該是字符串,不能使用正則表達式
> 是否大于
< 是否小于
!= 支持正則表達式
=~ 左側字符串能否被右邊的匹配,支持正則表達式
-z 字符串是否為空,空為真
-n 字符串是否非空,非空為真
注釋:使用 判斷[[ ]] ,使用正則表達式不能使用””括正則表達式
示例:
(1)==示例:
[root@centos7 ~]# a=root [root@centos7 ~]# [[ $a == root ]] [root@centos7 ~]# echo $? 0 [root@centos7 ~]#
(2)> < 比較ASCII碼大?。?/span>
[root@centos7 ~]# a=roou [root@centos7 ~]# [[ $a < root ]] [root@centos7 ~]# echo $? 1 [root@centos7 ~]# [[ $a > root ]] [root@centos7 ~]# echo $? 0 [root@centos7 ~]#
(3)=~ -z -n
[root@centos7 ~]# a=341234 [root@centos7 ~]# [[ $a =~ [[:digit:]]+ ]] [root@centos7 ~]# echo $? 0 [root@centos7 ~]# [[ -z $a ]] [root@centos7 ~]# echo $? 1 [root@centos7 ~]# [[ -n $a ]] [root@centos7 ~]# echo $? 0 [root@centos7 ~]#
10. 文件測試:
(1)存在行測試:
-a file 同-e 文件是否存在
(2)存在性及其類別測試,先判斷是否存在,然后是是否為符合條件(8種類型的文件都能測試):
-b 是否為塊設備文件
-c 是否為字符設備
-d 是否是目錄文件
-f 是否為普通文件
-h 同-L 存在是否是符號鏈接
-p 是否為管道文件
-S 是否為管道文件
文件權限測試(先判斷是否存在,再判斷權限):
-r 是否可讀
-w 是否可寫
-x 是否可執行
-g 是否擁有sgid
-u 是否擁有suid權限
-k 是否擁有sticky權限
(3)大小及訪問測試:
-s 是否存在且非空
-N 文件從上一次讀取之后是否被修改過
-O 當前有效用戶是否是文件屬主
-G當前有效用戶是否是文件屬組
11. 組合測試:&& || ! -a -o
[root@centos7 bin]# [ $USER == "jack" -o $USER == "root" ] [root@centos7 bin]# echo $? 0 [root@centos7 bin]# echo $USER root [root@centos7 bin]#
12. 使用read命令接受輸入
[root@centos7 ~]# cat cc.sh #!/bin/bash read -p "read some var: " aa bb dd echo "aa is: $aa bb is: $bb dd is: $dd " [root@centos7 ~]# bash cc.sh read some var: aa bb cc dd ee aa is: aa bb is: bb dd is: cc dd ee
注釋:讀入變量時每一個read定義的變量都會對應一個輸入,最后一個變量接受剩余的輸入,-p打印提示信息 ,-t超時時間
13. 條件選擇if語句:
(1)單分支:
格式:
if 判斷條件 ; then
條件為真的分支代碼
fi
(2)雙分支:
格式:
if 判斷條件 ; then
條件為真的分支代碼
else
條件為假的分支代碼
fi
(3)多分支:
格式:
if 判斷條件1 ; then
條件1為真分支代碼
elif 判斷條件2 ; then
條件2為真的分支代碼
else
所有條件為假的分支代碼
fi
示例:
[root@centos7 testdir]# cat /testdir/multiif.sh #!/bin/bash #author:jackcui if [ "$USER" == "root" ];then echo "hello root!" elif [ "$USER" == "jack" ];then echo "hello jack! how are you?" else echo "YOU ARE NOT PERMISION LOGIN!" fi [root@centos7 testdir]# bash multiif.sh hello root! [root@centos7 testdir]# chmod a+x multiif.sh [root@centos7 testdir]# su - jack Last login: Thu Aug 11 21:52:45 CST 2016 on pts/1 [jack@centos7 ~]$ bash /testdir/multiif.sh hello jack! how are you?
14. 條件判斷:case語句:
格式:
case 變量引用 in
pat1)
分支1
;;
pat2)
分支2
;;
*)
默認分支
;;
esac
示例:
[root@centos7 testdir]# cat caseTest.sh #!/bin/bash #author:jackcui read -p "Input conditional number: " con case $con in [124]) echo "this is first condition!" ;; 3) echo "this is third condition!" ;; 5) echo "this is 5th condition!" ;; *) echo "this conditional is false!" ;; esac
補充:case支持glob風格的通配符 * ? [] a|b
* 任意長度字符,?任意單個字符 [] 指定給范圍內的任意單個字符 a|b a或b
15.各種循環for,while,until
(1)for
格式:
for 變量名 in 列表;do
循環體
done
補充:in后的列表:1)直接給出列表。2){1..100},給出連續范圍。3)$(seq 起始 遞增 結束) 。4)使用通配符如*.conf 。5)變量引用 $@ , $*
for循環打印9*9乘法表
[root@centos7 bin]# cat 9\*9.sh #!/bin/bash i=1 j=1 for i in {1..9};do for j in `seq 1 $i`;do let mul=$i*$j echo -ne " $j*$i=$mul\t" done echo -e "\n" done
for循環打印國際棋盤(支持輸入顏色代碼,支持任意大小,顏色代碼41-47,
重置=0,黑色=40,紅色=41,綠色=42,黃色=43,藍色=44,洋紅=45,青色=46,白色=47 )
#!/bin/bash #author:jackcui read -p "please input width,color1 color2: " width col1 col2 for ((i=1;i<=8;i++));do for ((k=1;k<=width;k++));do for ((j=1;j<=8;j++));do for ((m=1;m<=width;m++));do let rem=(i+j)%2 if [ $rem -eq 0 ];then echo -en "\e[${col1}m \e[0m" else echo -en "\e[${col2}m \e[0m" fi done done echo -en "\n" done done
(2)while先判斷條件是否滿足,true則執行循環,否則跳出循環
格式:
while條件;do
循環體
done
示例:
while打印1-100的和
#!/bin/bash #author:jackcui i=1 while ((i<=100));do (( sum+=i++ )) done echo "the sum is : $sum"
(3)until false進入循環,直到條件滿足就跳出循環
格式:
until 條件;do
循環體
done
until示例:
[root@centos7 bin]# cat until99.sh #!/bin/bash i=1;j=1;sum=0 until [ $i -gt 9 ];do until [ $j -gt $i ];do ((sum=j*i)) echo -ne "$j*$i=$sum\t" ((j++)) done echo "" ((j=1)) ((i++)) done
原創文章,作者:jack_cui,如若轉載,請注明出處:http://www.www58058.com/37215