學習shell scripts

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生效

         對設置了本地變量的變量使用exportdeclare進行聲明

         export name=root 

         一般可以使用exportenv顯示所有的環境變量,unset取消變量的聲明

         declare –x name=root

4)局部變量:對某一斷代碼生效

5)位置變量:用$1,$2,${10}表示用于腳本運行時傳遞給它的參數

6)特殊變量:$?, $0, $*,$@,$#表示和參數相關的變量

4. 算術運算:

         bash支持算術運算,不支持浮點運算:+  –  *  /  %  ** (加,減,乘,除,取模,乘方)乘法符號有時需要轉義

1let var=算術表達式     eglet sum=3+5

2var=$[算術表達式]        eg: $[3+5]

3var=$((算術表達式))     eg: $((3+5))

4declare –i var=5

5var=$(expr arg1 arg2 arg3)

6echo ‘算術表達式’ |bc

7)產生隨機數:echo $ [$RANDOM%50]產生0-49之間的隨機數因為是對50取余數,random范圍(1-32767

5. 邏輯運算:(true 1,false 0

         與:全11

         或:有11

         非:取反

         短路與&&:第一個操作數為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  ab

15.各種循環for,while,until

1for

格式:

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

2while先判斷條件是否滿足,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"

3until  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

(0)
jack_cuijack_cui
上一篇 2016-08-18
下一篇 2016-08-18

相關推薦

  • Linux文件管理命令與bash的工作特性

    Shell程序在接受到用戶執行命令的請求時,在分析完成之后,最左側的字符串會被當作命令;
    命令查找機制:查找內部命令時,根據PATH環境變量中設定的目錄,從左至右逐個搜索目錄下的文件名;

    2018-03-11
  • Memcached實現Tomcat的session會話綁定

    memcached介紹:  Memcached是一個高性能的分布式內存對稱緩存系統;通過緩存查詢數據庫結果,介紹數據庫訪問次數,以提高web應用的速度、提高擴展性。  Memcached特點:   協議簡單   基于libevent的事件處理   內置內存存儲方式  memcached不互相通信的分…

    Linux干貨 2015-08-01
  • 馬哥教育網絡班N22期+第3周課程練習

    馬哥教育網絡班N22期+第3周課程練習 1、列出當前系統上所有已經登錄的用戶的用戶名,注意:同一個用戶登錄多次,則只顯示一次即可。 示例: [root@Red Hat Enterprise Linux Desktop]# who | cut -d' &#039…

    Linux干貨 2016-08-29
  • mysql.主從復制.讀寫分離.高可用.集群實戰

    架構圖如下: 1.按照架構圖所示,準備機器,做好時間同步,主機名解析 192.168.42.150 node1 [proxySQL keepalived]192.168.42.151 node2 [proxySQL keepalived]192.168.42.152 node3 [mysql-master wha]192.168.42.153 node4 […

    Linux干貨 2017-07-14
  • Java構造時成員初始化的陷阱

    讓我們先來看兩個類:Base和Derived類。注意其中的whenAmISet成員變量,和方法preProcess() public class Base {     Base() {         preP…

    Linux干貨 2015-04-03
  • Linux啟動和內核管理

                                        Linux啟動和內核管理 本章內容: centos5和centos6的啟動流程 服務管理 grub…

    系統運維 2016-09-21
欧美性久久久久