Linux伺服器Shell編程學習筆記

來源:互聯網
上載者:User

Shell指令碼編程學習入門是本文要介紹的內容,我們可以使用任意一種文字編輯器,比如gedit、kedit、emacs、vi等來編寫shell指令碼,它必須以如下行開始(必須放在檔案的第一行):

 代碼如下 複製代碼

#!/bin/sh

...注意:最好使用“!/bin/bash”而不是“!/bin/sh”,如果使用tc shell改為tcsh,其他類似。

符號#!用來告訴系統執行該sell指令碼的程式,本例使用/bin/sh。編輯結束並儲存後,如果要執行該shell指令碼,必須先使其可執行:

chmod +x filename此後在該shell指令碼所在目錄下,輸入 ./filename 即可執行該shell指令碼。

Shell裡的一些特殊符號

a []

shell離得函數

如果你寫過比較複雜的shell指令碼,就會發現可能在幾個地方使用了相同的代碼,這時如果用上函數,會方便很多。函數的大致樣子如下:

 代碼如下 複製代碼
functionname()
{
# inside the body $1 is the first argument given to the function
# $2 the second ...
body
}

你需要在每個指令碼的開始對函數進行聲明。

下面是一個名為xtitlebar的shell指令碼,它可以改變終端視窗的名稱。這裡使用了一個名為help的函數,該函數在shell指令碼中使用了兩次:

 代碼如下 複製代碼

#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
cat << HELP
xtitlebar -- change the name of an xterm, gnome-terminal or kde konsole
USAGE: xtitlebar [-h] "string_for_titelbar"
OPTIONS: -h help text
EXAMPLE: xtitlebar "cvs"
HELP
exit 0
}
# in case of error or if -h is given we call the function help:
[ -z "$1" ] && help
[ "$1" = "-h" ] && help
# send the escape sequence to change the xterm titelbar:
echo -e "33]0;$107"

#在shell指令碼中提供協助是一種很好的編程習慣,可以方便其他使用者(和自己)使用和理解指令碼。

命令列參數

我們已經見過$* 和 $1, $2 … $9 等特殊變數,這些特殊變數包含了使用者從命令列輸入的參數。迄今為止,我們僅僅瞭解了一些簡單的命令列文法(比如一些強制性的參數和查看協助的-h選項)。 但是在編寫更複雜的程式時,您可能會發現您需要更多的自訂的選項。通常的慣例是在所有可選的參數之前加一個減號,後面再加上參數值 (比如檔案名稱)。

有好多方法可以實現對輸入參數的分析,但是下面的使用case運算式的例子無疑是一個不錯的方法。

 代碼如下 複製代碼

#!/bin/sh

help()
{
   cat << HELP
   This is a generic command line parser demo.
   USAGE EXAMPLE: cmdparser -l hello -f -- -somefile1 somefile2
HELP
   exit 0
}

while [ -n "$1" ]; do
case $1 in
   -h) help;shift 1;; # function help is called
   -f) opt_f=1;shift 1;; # variable opt_f is set
   -l) opt_l=$2;shift 2;; # -l takes an argument -> shift by 2
   --) shift;break;; # end of options
   -*) echo "error: no such option $1. -h for help";exit 1;;
   *) break;;
esac
done

echo "opt_f is $opt_f"
echo "opt_l is $opt_l"
echo "first arg is $1"
echo "2nd arg is $2"

你可以這樣運行該指令碼:

 代碼如下 複製代碼

cmdparser -l hello -f -- -somefile1 somefile2


返回結果如下:

opt_f is 1
opt_l is hello
first arg is -somefile1
2nd arg is somefile2

這個shell指令碼是如何工作的呢?指令碼首先在所有輸入命令列參數中進行迴圈,將輸入參數與case運算式進行比較,如果匹配則設定一個變數並且移除該參數。根據unix系統的慣例,首先輸入的應該是包含減號的參數。

shell指令碼樣本

一般編程步驟

現在我們來討論編寫一個指令碼的一般步驟。任何優秀的指令碼都應該具有協助和輸入參數。寫一個架構指令碼(framework.sh),該shell指令碼包含了大多數指令碼需要的架構結構,是一個非常不錯的主意。這樣一來,當我們開始編寫新指令碼時,可以先執行如下命令:

 代碼如下 複製代碼

cp framework.sh myscript

然後再插入自己的函數。

讓我們來看看如下兩個樣本。

二進位到十進位的轉換

指令碼 b2d 將位元 (比如 1101) 轉換為相應的十進位數。這也是一個用expr命令進行數學運算的例子:

 代碼如下 複製代碼

#!/bin/sh
# vim: set sw=4 ts=4 et:
help()
{
   cat << HELP

b2d -- convert binary to decimal

USAGE: b2d [-h] binarynum

OPTIONS: -h help text

EXAMPLE: b2d 111010
will return 58
HELP
   exit 0
}

error()
{
   # print an error and exit
   echo "$1"
   exit 1
}

lastchar()
{
   # return the last character of a string in $rval
   if [ -z "$1" ]; then
      # empty string
      rval=""
      return
   fi
   # wc puts some space behind the output this is why we need sed:
   numofchar=`echo -n "$1" | sed 's/ //g' | wc -c `
   # now cut out the last char
   rval=`echo -n "$1" | cut -b $numofchar`
}

chop()
{
   # remove the last character in string and return it in $rval
   if [ -z "$1" ]; then
      # empty string
      rval=""
      return
   fi
   # wc puts some space behind the output this is why we need sed:
   numofchar=`echo -n "$1" | wc -c | sed 's/ //g' `
   if [ "$numofchar" = "1" ]; then
      # only one char in string
      rval=""
      return
   fi
   numofcharminus1=`expr $numofchar "-" 1`
   # now cut all but the last char:
   rval=`echo -n "$1" | cut -b -$numofcharminus1`
   #原來的 rval=`echo -n "$1" | cut -b 0-${numofcharminus1}`運行時出錯.
   #原因是cut從1開始計數,應該是cut -b 1-${numofcharminus1}
}

while [ -n "$1" ]; do
case $1 in
   -h) help;shift 1;; # function help is called
   --) shift;break;; # end of options
   -*) error "error: no such option $1. -h for help";;
   *) break;;
esac
done

# The main program
sum=0
weight=1
# one arg must be given:
[ -z "$1" ] && help
binnum="$1"
binnumorig="$1"

while [ -n "$binnum" ]; do
   lastchar "$binnum"
   if [ "$rval" = "1" ]; then
      sum=`expr "$weight" "+" "$sum"`
   fi
   # remove the last position in $binnum
   chop "$binnum"
   binnum="$rval"
   weight=`expr "$weight" "*" 2`
done

echo "binary $binnumorig is decimal $sum"

#該shell指令碼使用的演算法是利用十進位和位元權值 (1,2,4,8,16,..),比如二進位”10″可以這樣轉換成十進位:

 代碼如下 複製代碼

0 * 1 + 1 * 2 = 2

為了得到單個的位元我們是用了lastchar 函數。該函數使用wc –c計算字元個數,然後使用cut命令取出末尾一個字元。Chop函數的功能則是移除最後一個字元。

檔案迴圈轉載

你可能有這樣的需求並一直都這麼做:將所有發出郵件儲存到一個檔案中。但是過了幾個月之後,這個檔案可能會變得很大以至於該檔案的訪問速度變慢;下 面的shell指令碼 rotatefile 可以解決這個問題。這個指令碼可以重新命名郵件儲存檔案(假設為outmail)為outmail.1,而原來的outmail.1就變成了 outmail.2 等等…

 代碼如下 複製代碼

#!/bin/sh
# vim: set sw=4 ts=4 et:

ver="0.1"
help()
{
   cat << HELP
   rotatefile -- rotate the file name
   USAGE: rotatefile [-h] filename
   OPTIONS: -h help text
   EXAMPLE: rotatefile out

   This will e.g rename out.2 to out.3, out.1 to out.2, out to out.1[BR]
   and create an empty out-file

   The max number is 10
   version $ver
HELP
   exit 0
}

error()
{
   echo "$1"
   exit 1
}

while [ -n "$1" ]; do
   case $1 in
      -h) help;shift 1;;
      --) break;;
      -*) echo "error: no such option $1. -h for help";exit 1;;
      *) break;;
   esac
done

# input check:
if [ -z "$1" ] ; then
   error "ERROR: you must specify a file, use -h for help"
fi

filen="$1"
# rename any .1 , .2 etc file:
for n in 9 8 7 6 5 4 3 2 1; do
   if [ -f "$filen.$n" ]; then
      p=`expr $n + 1`
      echo "mv $filen.$n $filen.$p"
      mv $filen.$n $filen.$p
   fi
done

# rename the original file:
if [ -f "$filen" ]; then
   echo "mv $filen $filen.1"
   mv $filen $filen.1
fi

echo touch $filen
touch $filen

這個shell指令碼是如何工作的呢?在檢測到使用者提供了一個檔案名稱之後,首先進行一個9到1的迴圈;檔案名稱.9重新命名為檔案名稱.10,檔案名稱.8重 命名為檔案名稱. 9……等等。迴圈結束之後,把原始檔案命名為檔案名稱.1,同時建立一個和原始檔案同名的空檔案(touch $filen)

指令碼調試

最簡單的調試方法當然是使用echo命令。你可以在任何懷疑出錯的地方用echo列印變數值,這也是大部分shell程式員花費80%的時間用於調試的原因。Shell指令碼的好處在於無需重新編譯,而插入一個echo命令也不需要多少時間。

shell也有一個真正的偵錯模式,如果指令碼”strangescript”出錯,可以使用如下命令進行調試:

 代碼如下 複製代碼

sh -x strangescript7

上述命令會執行該指令碼,同時顯示所有變數的值。

shell指令碼中還有一個不執行指令碼只檢查文法的模式,命令如下:

 代碼如下 複製代碼

sh -n your_script


這個命令會返回所有語法錯誤。

我們希望你現在已經可以開始編寫自己的shell指令碼了,盡情享受這份樂趣吧!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.