1. 程式人生 > >shell編程基礎篇

shell編程基礎篇

前三 調試 命名 全局 表達式 簡單 程序 編程基礎 將他

重點註意,我們這裏介紹的是CentOS 6.7 版本的Linux

一、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命令執行。
   - 開頭加入版權、作者等信息(只是一個建議而已)
   - 腳本中盡量不要使用中文

   - 腳本名稱盡量以.sh結尾
   - 盡量添加多的註釋,這樣對調試和其他人使用腳本都有幫助。

 (3)shell的註釋

   - 單行註釋:“#”
   - 多行註釋:“:<<! !:”

 (4)腳本的執行?

   在Linux下執行shell有三種方式:
   - bash / sh 執行shell腳本
   - path/script.sh 直接執行腳本(腳本必須是可執行文件,並且首行有解釋器標識)
   - source script.sh或者. script.sh

這種方式可以將自身腳本中的變量的值或者函數等的返回值傳遞到父shell中執行。(當前操作的shell(父)---編寫的腳本執行(子)),也相當於父shell將子shell的腳本中命令讀取到自己的shell中然後執行。

二、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編程基礎篇