天天看點

shell程式設計 常用語句

http://blog.csdn.net/hainan16/article/category/861739

if 語句格式

if  條件

then

 Command

else

 Command

fi                              别忘了這個結尾

If語句忘了結尾fi

test.sh: line 14: syntax error: unexpected end of fi

        if 的三種條件表達式

if

command

then

if

 函數

then

 指令執行成功,等于傳回0 (比如grep ,找到比對)

執行失敗,傳回非0 (grep,沒找到比對)

if [ expression_r_r_r  ]

then 

 表達式結果為真,則傳回0,if把0值引向then

if test expression_r_r_r

then

 表達式結果為假,則傳回非0,if把非0值引向then

      [ ] &&  ——快捷if

[ -f "/etc/shadow" ] && echo "This computer uses shadow passwors"

   && 可以了解為then

    如果左邊的表達式為真則執行右邊的語句

        shell的if與c語言if的功能上的差別

 shell if     c語言if
0為真,走then  正好相反,非0走then

 不支援整數變量直接if

必須:if [ i –ne 0 ]

但支援字元串變量直接if

if [ str ] 如果字元串非0

 支援變量直接if

if (i )

=================================以command作為if 條件===================================

        以多條command或者函數作為if 條件

echo –n “input:”

read user

if

多條指令,這些指令之間相當于“and”(與)

grep $user /etc/passwd >/tmp/null      

who -u | grep $user

then             上邊的指令都執行成功,傳回值$?為0,0為真,運作then

 echo "$user has logged"

else     指令執行失敗,$?為1,運作else                            

 echo "$user has not logged"

fi   

# sh test.sh

input : macg

macg     pts/0        May 15 15:55   .          2075 (192.168.1.100)

macg has logged

# sh test.sh

input : ddd

ddd has not logged  

        以函數作為if條件  (函數就相當于command,函數的優點是其return值可以自定義)

if

以函數作為if條件,

getyn

then   函數reture值0為真,走then

echo " your answer is yes"

else  函數return值非0為假,走else

echo "your anser is no"

fi  

      if command  等價于 command+if $?

$ vi testsh.sh

#!/bin/sh

if

cat 111-tmp.txt | grep ting1

then

echo found

else

echo "no found"

fi

 $ vi testsh.sh

#!/bin/sh

cat 111-tmp.txt | grep ting1

if [ $? -eq 0 ]

then

echo $?

echo found

else

echo $?

echo "no found"

fi

$ sh testsh.sh

no found  

$ sh testsh.sh

1

no found

$ vi 111-tmp.txt

that is 222file

thisting1 is 111file

$ sh testsh.sh

thisting1 is 111file

found

$ vi 111-tmp.txt

that is 222file

thisting1 is 111file

$ sh testsh.sh

thisting1 is 111file

found

========================================以條件表達式作為 if條件=============================

        傳統if 從句子——以條件表達式作為 if條件

if [ 條件表達式 ]

then

  command

  command

  command

else

  command

  command

fi

   條件表達式

  • 檔案表達式

if [ -f  file ]    如果檔案存在

if [ -d ...   ]    如果目錄存在

if [ -s file  ]    如果檔案存在且非空 

if [ -r file   ]       如果檔案存在且可讀

if [ -w file   ]      如果檔案存在且可寫

if [ -x file   ]      如果檔案存在且可執行    

  • 整數變量表達式

if [ int1 -eq int2 ]    如果int1等于int2   

if [ int1 -ne int2 ]    如果不等于     

if [ int1 -ge int2 ]             如果>=

if [ int1 -gt int2 ]             如果>

if [ int1 -le int2 ]             如果<=

if [ int1 -lt int2 ]             如果<

  •    字元串變量表達式

If   [ $a = $b ]                               如果string1等于string2

                                                              字元串允許使用指派号做等号

if   [ $string1 !=   $string2 ]     如果string1不等于string2             

if  [ -n $string  ]             如果string 非空(非0),傳回0(true)   

if   [ -z $string   ]                         如果string 為空

if  [ $sting ]                  如果string 非空,傳回0 (和-n類似)      

        條件表達式引用變量要帶$

if [ a = b ] ;then    

echo equal

else

echo no equal

fi

[[email protected] ~]$ sh test.sh

input a:

5

input b:

5

no equal  (等于表達式沒比較$a和$b,而是比較和a和b,自然a!=b)

改正:

if [ $a = $b ] ;then       

echo equal

else

echo no equal

fi

[[email protected] ~]$ sh test.sh

input a:

5

input b:

5

equal

    -eq  -ne  -lt  -nt隻能用于整數,不适用于字元串,字元串等于用指派号=

[[email protected] ~]$ vi test.sh

echo -n "input your choice:"

read var

if  [ $var -eq "yes" ]

then

echo $var

fi

[[email protected] ~]$ sh -x test.sh

input your choice:

y

test.sh: line 3: test: y: integer expression_r_r_r expected

                       期望整數形式,即-eq不支援字元串

      =放在别的地方是指派,放在if [ ] 裡就是字元串等于,shell裡面沒有==的,那是c語言的等于

      無空格的字元串,可以加" ",也可以不加

[[email protected] ~]$ vi test.sh

echo "input a:"

read a

echo "input is $a"

if [ $a = 123 ] ; then

echo equal123

fi

[[email protected] ~]$ sh test.sh

input a:

123

input is 123

equal123 

     = 作為等于時,其兩邊都必須加空格,否則失效

等号也是操作符,必須和其他變量,關鍵字,用空格格開 (等号做指派号時正好相反,兩邊不能有空格)

[[email protected] ~]$ vi test.sh

echo "input your choice:"

read var

if [ $var="yes" ]

then

echo $var

echo "input is correct"

else

echo $var

echo "input error"

fi

[[email protected] ~]$ vi test.sh

echo "input your choice:"

read var

if [ $var = "yes" ]   在等号兩邊加空格

then

echo $var

echo "input is correct"

else

echo $var

echo "input error"

fi

[[email protected] ~]$ sh test.sh

input your choice:

y

y

input is correct

[[email protected] ~]$ sh test.sh

input your choice:

n    

n

input is correct 

輸錯了也走then,都走then,為什麼?

因為if把$var="yes"連讀成一個變量,而此變量為空,傳回1,則走else

 [[email protected] ~]$ sh test.sh

input your choice:

y

y

input error

[[email protected] ~]$ sh test.sh

input your choice:

no                       

no

input error

一切正常

        If  [  $ANS  ]     等價于  if [ -n $ANS ]

           如果字元串變量非空(then) , 空(else)

echo "input your choice:"

read ANS

if [ $ANS ]

then

echo no empty

else

echo empth

fi 

[[email protected] ~]$ sh test.sh

input your choice:                       回車

empth                                   說明“回車”就是空串

[[email protected] ~]$ sh test.sh

input your choice:

34

no empty 

        整數條件表達式,大于,小于 ,s hell裡沒有> 和< ,會被當作尖括号,隻有-ge,-gt,-le,lt

[[email protected] ~]$ vi test.sh

echo "input a:"

read a

if  [ $a -ge 100 ] ; then

echo 3bit

else

echo 2bit

fi

[[email protected] ~]$ sh test.sh

input a:

123

3bit

[[email protected] ~]$ sh test.sh

input a:

20

2bit

  整數操作符号-ge,-gt,-le,-lt, 别忘了加-

if  test $a  ge 100 ; then

[[email protected] ~]$ sh test.sh

test.sh: line 4: test: ge: binary operator expected

if  test $a -ge 100 ; then

[[email protected] ~]$ sh test.sh

input a:

123

3bit

============================邏輯表達式=========================================

    邏輯非 !                   條件表達式的相反

if [ ! 表達式 ]

if [ ! -d $num ]                                              如果不存在目錄$num

    邏輯與 –a                                       條件表達式的并列

if [ 表達式1   –a   表達式2 ]

        邏輯或 -o                             條件表達式的或

if [ 表達式1   –o 表達式2 ]

   邏輯表達式

  •     表達式與前面的=  != -d –f –x -ne -eq -lt等合用
  •     邏輯符号就正常的接其他表達式,沒有任何括号( ),就是并列

if [ -z "$JHHOME" -a -d $HOME/$num ]

  •     注意邏輯與-a與邏輯或-o很容易和其他字元串或檔案的運算符号搞混了

    最常見的指派形式,指派前對=兩邊的變量都進行評測

左邊測變量是否為空,右邊測目錄(值)是否存在(值是否有效)

[[email protected] ~]$ vi test.sh

:

echo "input the num:"

read num

echo "input is $num"

if [ -z "$JHHOME" -a -d $HOME/$num ]   如果變量$JHHOME為空,且$HOME/$num目錄存在

then

JHHOME=$HOME/$num                      則指派

fi

echo "JHHOME is $JHHOME"  

-----------------------

[[email protected] ~]$ sh test.sh

input the num:

ppp

input is ppp

JHHOME is

目錄-d $HOME/$num   不存在,是以$JHHOME沒被then指派

[[email protected] ~]$ mkdir ppp

[[email protected] ~]$ sh test.sh

input the num:

ppp

input is ppp

JHHOME is /home/macg/ppp

     一個-o的例子,其中卻揭示了”=”必須兩邊留白格的問題

echo "input your choice:"

read ANS

if [ $ANS="Yes" -o $ANS="yes" -o $ANS="y" -o $ANS="Y" ]

then

ANS="y"

else

ANS="n"

fi

echo $ANS

[[email protected] ~]$ sh test.sh

input your choice:

n

y

[[email protected] ~]$ sh test.sh

input your choice:

no

y

為什麼輸入不是yes,結果仍是y(走then)

因為=被連讀了,成了變量$ANS="Yes",而變量又為空,是以走else了

[[email protected] ~]$ vi test.sh

echo "input your choice:"

read ANS    echo "input your choice:"

read ANS

if [ $ANS = "Yes" -o $ANS = "yes" -o $ANS = "y" -o $ANS = "Y" ]

then

ANS="y"

else

ANS="n"

fi

echo $ANS

[[email protected] ~]$ sh test.sh

input your choice:

no

n

[[email protected] ~]$ sh test.sh

input your choice:

yes

y

[[email protected] ~]$ sh test.sh

input your choice:

y

y

===================以   test 條件表達式作為if條件===================================

        if test $num -eq 0      等價于   if [ $num –eq 0 ]

      test  表達式,沒有 [  ]

if test $num -eq 0                               

then

echo "try again"

else

echo "good"

fi

    man test

[[email protected] ~]$ man test

[(1)                             User Commands                            [(1)

SYNOPSIS

       test EXPRESSION

       [ EXPRESSION ]

       [-n] STRING

              the length of STRING is nonzero          -n和直接$str都是非0條件

       -z STRING

              the length of STRING is zero

       STRING1 = STRING2

              the strings are equal

       STRING1 != STRING2

              the strings are not equal

       INTEGER1 -eq INTEGER2

              INTEGER1 is equal to INTEGER2

       INTEGER1 -ge INTEGER2

              INTEGER1 is greater than or equal to INTEGER2

       INTEGER1 -gt INTEGER2

              INTEGER1 is greater than INTEGER2

       INTEGER1 -le INTEGER2

              INTEGER1 is less than or equal to INTEGER2

       INTEGER1 -lt INTEGER2

              INTEGER1 is less than INTEGER2

       INTEGER1 -ne INTEGER2

              INTEGER1 is not equal to INTEGER2

       FILE1 -nt FILE2

              FILE1 is newer (modification date) than FILE2

       FILE1 -ot FILE2

              FILE1 is older than FILE2

       -b FILE

              FILE exists and is block special

       -c FILE

              FILE exists and is character special

       -d FILE

              FILE exists and is a directory

       -e FILE

              FILE exists                                 檔案存在

       -f FILE

              FILE exists and is a regular file     檔案存在且是普通檔案

       -h FILE

              FILE exists and is a symbolic link (same as -L)

       -L FILE

              FILE exists and is a symbolic link (same as -h)

       -G FILE

              FILE exists and is owned by the effective group ID

       -O FILE

              FILE exists and is owned by the effective user ID

       -p FILE

              FILE exists and is a named pipe

       -s FILE

              FILE exists and has a size greater than zero

       -S FILE

              FILE exists and is a socket

       -w FILE

              FILE exists and is writable

       -x FILE

FILE exists and is executable

======================if簡化語句=================================

        最常用的簡化if語句

   && 如果是“前面”,則“後面”

[ -f /var/run/dhcpd.pid ] && rm /var/run/dhcpd.pid    檢查 檔案是否存在,如果存在就删掉

   ||   如果不是“前面”,則後面

[ -f /usr/sbin/dhcpd ] || exit 0    檢驗檔案是否存在,如果存在就退出

        用簡化 if 和$1,$2,$3來檢測參數,不合理就調用help

[ -z "$1" ] && help                 如果第一個參數不存在(-z  字元串長度為0 )

[ "$1" = "-h" ] && help                                              如果第一個參數是-h,就顯示help

例子

#!/bin/sh

[ -f "/etc/sysconfig/network-scripts/ifcfg-eth0" ] && rm -f /etc/sysconfig/network-scripts/ifcfg-eth0

cp ifcfg-eth0.bridge /etc/sysconfig/network-scripts/ifcfg-eth0

[ -f "/etc/sysconfig/network-scripts/ifcfg-eth1" ] && rm -f /etc/sysconfig/network-scripts/ifcfg-eth1

cp ifcfg-eth1.bridge /etc/sysconfig/network-scripts/ifcfg-eth1

[ -f "/etc/sysconfig/network-scripts/ifcfg-eth0:1" ] && rm -f /etc/sysconfig/network-scripts/ifcfg-eth0:1

  case語句格式

# vi test.sh

:

echo "input : "

read num

echo "the input data is $num"

case $num in

1) echo "January";;     雙分号結束

2) echo "Feburary";;

5) echo "may"          每個case可以有多條指令       

   echo "sdfd"

   echo "sdf";;        但最後一條指令一定是雙分号結束

*) echo "not correct input";;   *)是其他值、default的意思      

esac    

# sh ./test.sh

input :

2

the input data is 2

Feburary

# sh ./test.sh

input :

ter

the input data is ter

not correct input   

        case 語句如果某個選項沒有任何語句,也要加;; 否則會出下邊錯誤

test: line 166: syntax error near  unexpected token `)'

test: line 166: `"system hostname config")'

        為什麼輸入no,仍不比對到[no]

原來[]是專門針對 單字元 的值,如果用[no],就是n和o之一

case $yn in  

 [no]) return 1;;

  * )  echo "only accept Y,y,N,n,YES,yes,NO,no" >&2;;

[[email protected] ~]$ sh test.sh

enter y/n :

no                           

only accept Y,y,N,n,YES,yes,NO,no

改正

case $yn in  

  no) return 1;;

  NO) return 1;;

  * ) echo "only accept Y,y,N,n,YES,yes,NO,no" >&2;;

 esac

[[email protected] ~]$ sh test.sh

enter y/n :

no                            

        一個getyn()函數的例子

getyn( )

{

while echo "enter y/n :"

do

 read yn

 case $yn in

  [Yy]) return 0 ;;

  yes) return 0 ;;

  YES) return 0 ;;

  [Nn]) return 1 ;;

  no) return 1;;

  NO) return 1;;

  * ) echo "only accept Y,y,N,n,YES,yes,NO,no" ;;

 esac

done

}

if

getyn  調用函數      以函數作為if條件,必須用if command法

then     注意0為真

echo " your answer is yes"

else

echo "your anser is no"

fi   

        if,  case,比對字元串最常見,但如何比對一段很長的輸出,一堆文字?最好方法,用“*”,如:*"command not found"*

[[email protected] ~]$ vi test.sh

var=$(ls -l $1)      $()取指令輸出,$1是指令行參數

echo "output is $var"

case $var in

"-rw-rw-r--"*) echo "this is not a execute file";;

"-rwxrwxr-x"*) echo "this is a execute file";

注意*在雙引号外邊

esac

[[email protected] ~]$ sh test.sh 22.txt

output is -rw-rw-r--  1 macg macg 15 Jun  9 19:00 22.txt

this is not a execute file

[[email protected] ~]$ chmod +x 22.txt

[[email protected] ~]$ sh test.sh 22.txt

output is -rwxrwxr-x  1 macg macg 15 Jun  9 19:00 22.txt

this is a execute file

       例2.比對file指令輸出的一堆文字,以獲知檔案類型

用’ ’ 取輸出,然後用CASE+*對輸出做修飾處理.

[[email protected] ~]$ vi test.sh

var=`file $1`        `  `和$( )作用相同,是取指令輸出

echo "output is $var"

case $var in

"$1: ASCII text"*) echo "this is a text file";;

"$1: directory"*) echo "this is a directory";;

注意*在雙引号外邊

esac    

[[email protected] ~]$ sh test.sh 22.txt

output is 22.txt: ASCII text

this is a text file

[[email protected] ~]$ sh test.sh test-dir

output is test-dir: directory

this is a directory

           最典型的shell case指令比對指令行,用于sys v啟動腳本的start|stop|restart|status處理

   case     "$@"     in       

($@ 字元串數組:以"參數1" "參數2" ... 的字元串數組形式儲存所有參數 

對于單個參數的情況,$@就是一個字元串)

   start)       

                   echo     -n     "Starting     firewall..."       

                   。。。   

                   echo     "OK!"       

                   exit     0       

                   ;;       

   stop)       

                   echo     -n     "Stopping     firewall..."

                   。。。     

                   exit     0       

                   ;;     

restart )       

                    $0   stop     $0即執行原始程式            

                    $0   start        

                   ;;       

status)       

                   clear       

                   echo     ">------------------------------------------"       

                   iptables     -L       

                   echo     ">------------------------------------------"       

                   iptables     -t     nat     -L     POSTROUTING       

                   exit     0     

         *)       

                   echo     "Usage:     $0     {start|stop|restart|status}"       

                   exit     1       

   esac     

=====================================while語句========================================

while語句格式

while   表達式

  do    

  command

  command

  done 

      while 和 if 的條件表達式完全相同,也是[ ] 或commad或test

 While 表達式  If 表達式
 表達式值為0,則循環繼續  表達式值為0,then
 表達式值為非0,則循環停止  表達式值為非0,else

   最基本的i++ 條件型循環

i=1

while [ $i -lt 10 ]

do

sed -n "${i}p" 111.txt

i=$(($i+1))       必須雙層括号

done   

        指令型while 循環

while command      指令傳回值0(成功執行),循環繼續

pause函數,輸入任何值繼續,輸入q退出程式

pause()

{

while echo "Press <return> to proceed or type q to quit:"

do

read cmd

case $cmd in

 [qQ]) exit 1;;       exit直接退到底,退出shell script 

 "") break;;          break跳出循環

 *) continue;;        continue跳到循環底,重新開始新循環循環

esac

done

While echo …               此指令沒有失敗的可能,是以必須有break,return,exit之類的指令

   while 關鍵字

break———— 用來跳出循環

continue—— 用來不執行餘下的部分,直接跳到下一個循環

===========================================FOR語句===================================

      for語句格式

for   表達式

  do    

  command

  command

  done 

        i++,n=n+1 必須用雙層括号  $(($num+1)) ,單層括号$($num+1)不管用       

[[email protected] home]# vi test.sh

:

echo "input num:"

read num

echo "input is $num"

num=$($num+1)

echo "new num is $num"

[[email protected] home]# sh test.sh

input num:

3

input is 3

test.sh: line 6: 3+1: command not found

new num is

[[email protected] home]# vi test.sh

:

echo "input num:"

read num

echo "input is $num"

num=$(($num+1))        

echo "new num is $num"

[[email protected] home]# sh test.sh

input num:

3

input is 3

new num is 4 

      (( ))與[ ]作用完全相同

echo input:

read i

i=$(($i+1))

echo $i  

echo input:

read i

i=$[$i+1]

echo $i

[[email protected] ~]$ sh ttt.sh

input:

6

7

[[email protected] ~]$ sh ttt.sh

input:

6

7

             再證明(( ))與[ ]完全相同--------if (( ))

if (( $# != 3 )); then

 echo "usage: $0 host user passwd"

    exit 1

fi

if [ $# != 3 ]; then

 echo "usage: $0 host user passwd"

    exit 1

fi

[[email protected] ~]$ sh ttt.sh 1 2

usage: ttt.sh host user passwd

[[email protected] ~]$ sh ttt.sh 1 2

usage: ttt.sh host user passwd

      $foo=$(($foo+1))                  # 運作的時候這個地方報錯

給變量指派,左邊的變量不需要加 $ 符号,

foo=$(($foo+1))                                

指派=,read,export都不需要加變量$