shell編程基礎篇
一、shell的介紹
(1)什麽是shell?
shell是一個命令解釋器,它在操作系統的最外層,負責直接與用戶對話,把用戶的輸入解釋給操作系統,並處理各種各樣的操作系統的輸出的結果,輸出到屏幕返回給用戶。這種對話方式可以是交互式的(從鍵盤輸入,立刻得到shell的回應),或者非交互式的。Shell:是一門弱類型(語法叫寬松)的語言較為通用的shell有bash shell。shell腳本語言的種類也比較多:Bourne shell (包括:sh,ksh,and bash)、C Shell (包括:csh and tcsh)。當然我們這裏主要說的是bash shell!!!!!
(2)shell的編寫規範
- 腳本的開頭第一行為:#!/bin/bash 或者 #!/bin/sh。這是因為#!又稱為幻數,在執行bash腳本的時候,內核會根據它來確定該用哪一個程序來解釋腳本中的內容,這一行必須在腳本的頂端的第一行。其實bash和sh是一個文件,只不過在Linux中/bin/sh是一個鏈接文件實際的指向為/bin/bash。
- 如果在腳本的第一行沒有指定解釋器,在運行的時候需要使用bash命令執行。
- 開頭加入版權、作者等信息(只是一個建議而已)
- 腳本中盡量不要使用中文
- 盡量添加多的註釋,這樣對調試和其他人使用腳本都有幫助。
(3)shell的註釋
- 單行註釋:“#”
- 多行註釋:“:<<! !:”
(4)腳本的執行?
在Linux下執行shell有三種方式:
- bash / sh 執行shell腳本
- path/script.sh 直接執行腳本(腳本必須是可執行文件,並且首行有解釋器標識)
- source script.sh或者. script.sh
二、shell中的變量
(1)shell的變量介紹
shell中的變量分為兩類:環境變量(全局變量)和局部變量。
環境變量:在創建他們的shell以及派生出來的任意子進程的shell中均可以使用。
局部變量:只能在創建他們的shell函數或者腳本中使用。
(2)環境變量
用於定義shell的運行環境,保證shell的正確執行。所有的環境變量都是系統的全局變量可以用於所有子進程中,包括編輯器、shell腳本和各類應用。
例:
#聲明
export 變量名 = 變量的值
變量名=變量的值;export 變量名
declare -x 變量名=變量的值
#系統內置的環境變量介紹:
$HOME 用戶的家目錄
$USER 當前用戶
$UID 當前用戶的uid
$SHELL 當前用戶使用的shell
$HISTISZE 記錄在命令行歷史文件中的命令行數
$PATH 執行命令時尋找的目錄
$PWD 當前用戶的家目錄
$PS1 用戶登錄的環境變量 [root@test ~]
$TMOUT 用戶登錄的超時時間
#顯示和取消環境變量
顯示:echo $變量
set和env 顯示所有的環境變量。
取消:unset 變量名。
readonly:設置只讀變量
(3)局部變量
局部變量也成為本地變量,在用戶當前的shell中使用,如果退出shell,則失效。
例:
#聲明:
變量名=value(數字、字母、下劃線組成)
這裏需要介紹一下Linux下的雙引號、單引號和不加引號的區別:
由上面的例子可以看出:
單引號:所見即所得,單引號內的內容原樣輸出。
雙引號:如果內容中有變量等,會將變量解析出來,然後將最終的結果打印
不加引號:把內容輸出出來,如果有連續的空格會將空格合並為一個空格,然後將變量等解析出來在輸出。
反引號:把字符串當做命令去執行。
註意:一般的在使用命令的時候,變量的引用盡量不要加引號或雙引號。但是在做字符串判斷的時候一般的都需要加上引號。
(4)特殊變量
#介紹
$0:表示獲取當前腳本的腳本名、
$n:獲取當前執行的shell腳本的第n個參數,n=1..9,如果n大於10,用${10}
$#:獲取當前shell命令行中參數的個數
$\*:表示參數列表
$@:表示參數列表
$$:獲取當前shell的進程號
$!:執行上一個指令的PID
$?:獲取執行的上一個指令的返回值(0表示成功,非零表示失敗)
$_:在此之前執行的命令或腳本的最後一個參數
具體的小編在這裏給大家補充兩點:
- $*和$@的區別
大家可以運行上面的腳本並傳入參數,看看具體如何打印的,就大概明白兩者的區別了。
- $?返回值得介紹(有助於錯誤排查):
0:表示執行成功
2:權限拒絕
1~125:表示運行失敗,腳本命令,系統命令,錯誤或者參數傳遞錯誤
126:找到該命令,但是無法執行
127:未找到該命令
大於128:命令被系統強制停止
三、shell變量的進階操作
(1)shell變量的計算
好的shell腳本,變量的計算顯然是離不開的,可以使用(())、let、expr、bc、$[]變量進行計算,這裏給大家總結幾個常用的。
(()):
只能用於整數計算。常用,效率高。
#用法
a=$((1+1)); 需要使用$進行修飾
((a=1+1)) 此種方式不需要用$修飾
a=((3>1)) 也可以寫入比較,正確返回1,錯誤返回0
#實現簡單的計算器:
#!/bin/sh
read -p "Please input first num:" num1
read -p "Please input operators:" operators
read -p "Please input second num:" num2
sum=$(($num1$operators$num2))
echo "$num1 $operators $num2 = $sum"
let:
用作簡單的整數計算,let賦值表達式。
#例:
[root@test zy]# i=2
[root@test zy]# i=i+8 #表示字符串的拼接
[root@test zy]# echo $i #打印i+8
[root@test zy]# i=2
[root@test zy]# let i=i+8 #表示數值計算
[root@test zy]# echo $i #打印10
bc:
可以實現整數、小數的運算,接受標準輸入。
例:
[root@test zy]# i=2
[root@test zy]# echo "$i+2.4"|bc #打印4.4
#實現1+2…10的計算
#!/bin/sh
str=""
for i in `seq 10`
do
if [ $i -eq 10 ];then
str=$str$i
else
str=$str$i"+"
fi
done
sum=`echo "$str"|bc`
echo "$str=$sum"
#保留小數
[root@test zy]# echo "scale=2;3.14/2.1"|bc #保留兩位小數
$[]:
a=$[1+1],與(())類似,但是[]不能講變量提取到[]中。
(2)變量子串的常見操作
#子串的操作
${#string} 返回string這個變量的長度
${strting:position} 在變量string中從position開始提取子串(從0開始,取到結尾)
${string:pos:len} 在變量string中從pos開始提取子串,提取長度為len
${string#sub} 在變量string中從頭開始,刪除sub匹配的子串
${string%sub} 在變量string中從末尾開始,刪除sub匹配的子串
${string/old/new} 在變量string中將old內容,替換成new(只替換第一個找到的)
${string//old/new} 在變量string中將old內容,替換成new(替換所有找到的內容)
${value:=word} 給變量賦默認值,LOD=${value:=word}, $LOD的值為word
${value:index:len} 從index位置開始取值,向後取len長度
#變量的替換
${value:-word} 當value定義或者為空時,返回後面的值,當value已經有值了就返回value的值, 只是針對返回值,value本身仍然沒有值
#例:
result=${value:-word}
echo $result #打印word
echo $value #打印空
${value:=word} 當value定義或者為空時,返回後面的值, value的值也會改變,當value已經有值了就返回value的值,
#例:
result=${value:=word}
echo $result #打印word
echo $value #打印word
${value:?”not default”} 如果變量名存在且非空,則返回變量的值,否則顯示“變量名:message“,並退出當前腳本
#例:
[root@test zy]# ${key:?"not default"} #打印 -bash: key: not default
${value:+word} 如果變量存在且不為空,則返回後面的值,否則返回null。用於測試變量是否存在
#例:
[root@test zy]# echo ${result:+word} #打印:word(已定義)
[root@test zy]# echo ${key:+word} #打印 空 (未定義)
${result-value} 與${value:-word}相同
這裏給大家介紹一個具體的例子看看,變量操作的重要意義:
#將某目錄下的所有.jpg的文件改成,以.JPG的結尾
#方法一:
for i in `ls *.jpg`;do mv $i ${i/%jpg/JPG} ; done;
#方法二:
rename .jpg .JPG \*
#計算變量的長度
#方法一:
[root@test zy]# echo ${#chars}
#方法二:
[root@test zy]# echo $chars|wc –c #會多打印末尾的換行
#方法三:
[root@test zy]# echo $(expr length "$chars")
#方法四:
echo $value|awk -F’’ ‘BEFORE{count=0} {count++} END{print count}’
看似不使用變量操作,就可以使用命令解決我們的問題,但是執行的效率呢?
我們可以在命令前加上time 查看命令執行的時間:
[root@test ~]# time for i in seq 1111
;do count=${#chars};done;
同樣的可以查看上面所有的方法的執行時間,一對比,就只到變量操作的強大體現在哪裏。這裏小編給大家總結一下(以前三種方法為例):方法一>方法三>方法二 #最終使用內置的功能效率最高
四、shell中通用常用命令介紹
(1)echo命令
對於這個命令大家可能熟悉的不能再熟悉了,將指定內容顯示到標準輸出。
例:
[root@test my_test]# echo "abc" #會打印 abc
[root@test my_test]# echo -n "abc\tabc" #會打印 abc\tabc
[root@test my_test]# echo -e "abc\tabc" #會打印 abc abc
[root@test my_test]# echo -n "abc" #默認的echo命令是打印之後換行,-n表示不換行
(2)eval命令
讀入參數,將他們組成一個新命令執行
[root@test my_test]# eval "echo " "1" #打印1
(3)exec命令
當shell執行到exec語句時,不會去創建新的子進程,而是轉去執行命令,當指定的命令執行完成後,shell就結束了,所以exec後的命令不會執行。
#腳本
#!/bin/sh
echo "before exec"
exec echo "exec run"
echo "after exec"
結果exec 語句之後的命令就不會執行了,而且退出了當前的shell
(4)export命令
將申明的變量導出,成為全局變量。
(5)read命令
從標準輸出中讀取字符串,傳遞給變量.
#介紹:
-p 設置提示信息,例:read –p “請輸入:” value
-t time(second) ,設置超時時間。例:read –t 3 –p“請輸入胡” value
(6)shift命令
shift語句按如下方式重命名所有的位置變量,如,$2變成$1,$3變成$2…,即在程序中每使用一次shift命令,都使得所有的位置信息依次向左移動一個位置。$#也會依次減少,直到為0
例:
#!/bin/sh
# script-name : test.sh
echo $#
shift
echo $#
shift
echo $#
shift
[root@test my_test]#sh test.sh 1 2 3 #最終會打印 3 2 1
(7)exit命令
表示退出當前的shell腳本,後面可接參數,0:表示正常退出,非零表示異常退出。
shell編程基礎篇