shell指令碼基礎

來源:互聯網
上載者:User
常見的shell:--------------來源於“鳥哥的LINUX私房菜”

由於早年的 Unix 年代,發展者眾,所以由於 shell 依據發展者的不同就有許多的版本,例如

常聽到的 Bourne SHell (sh) 、
在 Sun 裡頭預設的 C SHell、
商業上常用的 K SHell,
還有 TCSH 等等,每一種 Shell 都各有其特點。

至於 Linux 使用的這一種版本就稱為『 Bourne Again SHell (簡稱 bash ) 』,
這個 Shell 是 Bourne Shell 的增強版本,也是基準於 GNU 的架構下發展出來的呦!

在介紹 shell 的優點之前,先來說一說 shell 的簡單曆史吧:第一個流行的 shell 是由 Steven Bourne 發展出來的,為了紀念他所以就稱為 Bourne shell ,或直接簡稱為 sh !而後來另一個廣為流傳的 shell 是由柏克萊大學的 Bill Joy 設計依附於 BSD 版的 Unix 系統中的 shell ,這個 shell 的文法有點類似 C 語言,所以才得名為 C shell ,簡稱為 csh !由於在學術界 Sun 主機勢力相當的龐大,而 Sun 主要是 BSD 的分支之一,所以 C shell 也是另一個很重要而且流傳很廣的 shell 之一(因為太多的程式設計師使用的就是 C 語言啦!)!

====================================================================

Shell編程概述------------來源於:http://fanqiang.chinaunix.net/a4/b1/20011115/0708001566.html

 

在DOS 中,你可能會從事一些例行的重覆性工作,此時你會將這些重覆性的命令寫成批次檔,只要執行這個批次檔就等於執行這些命令。大家會問在UNIX中是否有批次處理這個東東,答案是有的。在UNIX中不只有如DOS 的批次處理,它的功能比起DOS 更強大,相對地也較複雜,已經和一般的高階語言不相上下。在UNIX中大家都不叫做批次檔,而叫做Shell Script。 

一般而言,Shell Script的地位和其它的可執行檔(或命令)是完全相同的,只不過Shell Script是以文字檔的方式儲存,而非二進位檔。而執行Shell Script時,必須有一個程式將其內容轉成一道道的命令執行,而這個程式其實就是Shell ,這也就是為什麽我們叫做Shell Script的原因(往後我們稱為Script)。不同Shell 的Script基本上會有一些差異,所以我們不能將寫給A shell 的Script用B shell 執行。而在UNIX中大家最常使用Bourne Shell以及C Shell ,所以這堂課就介紹這兩種Script的寫法。 

將文字檔設為可執行檔Shell Script 

如果我們已經寫好Script,如何將其設成可執行檔呢?因為Script其實是一個可執行檔,所以必須將其存取權設定成可執行。我們可以使用下列命令更改存取權: 
chmod u+x filename 只有自己可以執行,其它人不能執行 
chmod ug+x filename 只有自己以及同一群可以執行,其它人不能執行 
chmod +x filename 所有人都可以執行 

而我們如何指定使用那一個Shell 來解釋所寫的Script呢?幾種基本的指定方式如下所述: 
1. 如果Script的第一個非空白字元不是"#",則它會使用Bourne Shell。 
2. 如果Script的第一個非空白字元是"#"時,但不以"#!"開頭時,則它會使用C Shell。 
3. 如果Script以"#!"開頭,則"#!"後面所寫的就是所使用的Shell,而且要將整個路徑名稱指出來。 

這裡建議使用第三種方式指定Shell ,以確保所執行的就是所要的。Bourne Shell的路徑名稱為/bin/sh ,而C Shell 則為/bin/csh。 

1. 使用Bourne Shell
┌——————————┐ ┌——————————┐
│echo enter filename │ │#!/bin/sh │
│ . │ or │ . │
│ . │ │ . │
│ . │ │ . │
└——————————┘ └——————————┘

2. 使用C Shell
┌——————————┐ ┌——————————┐
│# C Shell Script │ │#!/bin/csh │
│ . │ │ . │
│ . │ │ . │
│ . │ │ . │
└——————————┘ └——————————┘

3. 使用/etc/perl
┌——————————┐
│#! /etc/perl │
│ . │
│ . │
│ . │
└——————————┘

除了在Script內指定所使用的Shell 外,你也可以在命令列中強制指定。比如你要用C Shell 執行某個Script,你可以下這個命令: 
csh filename 

此時的Script的存取權就不一定要為可執行檔,其內部所指定的Shell 也會無效,詳細的情形後面會討論。 

□Script的基本結構及觀念 

Script是以行為單位,我們所寫的Script會被分解成一行一行來執行。而每一行可以是命令、註解、或是流程式控制制指令等。如果某一行尚未完成,可以在行末加上"\" ,這個時候下一行的內容就會接到這一行的後面,成為同一行,如下 

┌———————————┐
│echo The message is \ │
│too long so we have \ │
│to split it into \ │
│several lines │
└———————————┘

當Script中出現"#" 時,再它後面的同一行文字即為註解,Shell 不會對其翻譯。 

在Script中要執行一個命令的方法和在命令列中一樣,你可以前景或背景執行,執行命令時也會需要設定一些環境變數。 

Script的流程式控制制和一般高階語言的流程式控制制沒有什麽兩樣,也和高階語言一樣有副程式。這些使得Script的功能更加強大。 

為了達到與高階語言相同的效果,我們也可以在Script中設定變數,如此使Script 成為一個名付其實的高階語言。 

□Bourne Shell 

一、變數 

Bourne Shell的變數型態只有字串變數,所以要使用數值運算則必須靠外部命令達 成目的。而其變數種類有下列幾種: 

1. 使用者變數 

這是最常使用的變數,我們可以任何不包含空白字元的字串來當做變數名稱。 設定變數值時則用下列方式: 
var=string 

取用變數時則在變數名稱前加上一"$" 號。 

┌———————┐
│name=Tom │
│echo name │
│echo $name │
└———————┘
結果如下:
name
Tom

2. 系統變數(環境變數) 

和使用者變數相似,只不過此種變數會將其值傳給其所執行的命令。要將一使 用者變數設定為系統變數,只要加上: 
export var 

┌———————┐
│name=Tom │
│export name │
└———————┘

以下是使用者一進入系統之後就已設定好的系統變數: 
$HOME 使用者自己的目錄 
$PATH 執行命令時所搜尋的目錄 
$TZ 時區 
$MAILCHECK 每隔多少秒檢查是否有新的信件 
$PS1 在命令列時的提示號 
$PS2 當命令尚未打完時,Shell 要求再輸入時的提示號 
$MANPATH man 指令的搜尋路徑 

3. 唯讀的使用者變數 

和使用者變數相似,只不過這些變數不能被改變。要將使用者變數設成唯讀的 ,只要加上: 
readonly var 

而若只打readonly則會列出所有唯讀的變數。還有一點,系統變數不可以設定 成唯讀的。 

┌———————┐
│name=Tom │
│readonly name │
│echo $name │
│name=John │
│readonly │
└———————┘

結果如下:
Tom
name: is read only
readonly name
readonly ......

4. 特殊變數 

有些變數是一開始執行Script時就會設定,並且不以加以修改,但我們不叫它 唯讀的系統變數,而叫它特殊變數(有些書會叫它唯讀的系統變數),因為這 些變數是一執行指令碼時就有了,況且使用者無法將一般的系統變數設定成唯讀 的。以下是一些等殊變數: 
$0 指令檔本身的名字
$n 這個指令碼的第n個命令列參數,n=1..9 
$* 所有命令列參數組成一個整體,作為一個“單詞”
$# 命令列參數的個數 
$$ Shell進程自己的PID 
$! Shell進程最後啟動的後台進程的PID 
$? 最後一次執行的命令的返回碼
 $@ 將所有命令列參數看作是多個“單詞”

當你執行這個程式時的參數數目超過9 個時,我們可以使用shift 命令將參數 往前移一格,如此即可使用第10個以後的參數。除此之外,吾人可以用set 命 令改變$n及$*,方法如下: 
set string 

如此$*的值即為string,而分解後則會放入$n。如果set 命令後面沒有參數, 則會列出所有已經設定的變數以及其值。 

檔名:ex1 參數:this is a test 

┌———————————┐
│echo Filename: $0 │
│echo Arguments: $* │
│echo No. of args.: $# │
│echo 2nd arg.: $2 │
│shift │
│echo No. of args.: $# │
│echo 2nd arg.: $2 │
│set hello, everyone │
│echo Arguments: $* │
│echo 2nd arg.: $2 │
└———————————┘
結果如下:
Filename: ex1
Arguments: this is a test
No. of args.: 4
2nd arg.: is
No. of args.: 3
2nd arg.: a
Arguments: hello, everyone
2nd arg.: everyone

值得一提的是,當你想從鍵盤輸入一變數值時,你可以使用下面的命令: 
read var1 var2..... 

這時read會將一個字分給一個變數。如果輸入的字比變數還多,最後一個變數會將剩下的字當成其值。如果輸入的字比變數還少,則後面的變數會設成空字串。 如果需要處理數值運算,我們可以使用expr命令。其參數及輸出資料行於附錄A。 

二、執行命令 

在Bourne Shell中有五種方法執行一個命令,而這五種方式所產生的果有些許的不 同。 

1. 直接下命令 
這個方式和在命令列中直接下命令的效果一樣。 

2. 使用sh命令 
sh command 
這個檔案必須是Bourne Shell的Script,但這個檔案並不一定要設成可執行。 除此之外和直接下命令的方式一樣。 

3. 使用"."命令 
. command 

這時和使用sh命令相似,只不過它不像sh一般會產生新的process ,相反地, 它會在原有的process 下完成工作。 

4. 使用exec命令 
exec command 
此時這個Script將會被所執行的命令所取代。當這個命令執行完畢之後,這個 Script也會隨之結束。 

5. 使用命令替換 
這是一個相當有用的方法。如果想要使某個命令的輸出成為另一個命令的參數 時,就一定要使用這個方法。我們將命令列於兩個"`" 號之間,而Shell 會以 這個命令執行後的輸出結果代替這個命令以及兩個"`" 符號。 

str='Current directory is '`pwd` 
echo $str 
結果如下: 
Current directory is /users/cc/mgtsai 
這個意思是pwd 這個命令輸出"/users/cc/mgtsai",而後整個字串代替原 來的`pwd` 設定str 變數,所以str 變數的內容則會有pwd 命令的輸出。 

number=`expr $number + 1` 
這就是先前所提要作數值運算的方法,基本上expr命令只將運算式解,而 後輸出到標準輸出上。如果要將某變數設定成其值,非得靠命令替換的方 式不可。這個例子是將number變數的值加1 後再存回number變數。 

三、流程式控制制 

在介紹流程式控制制之前,我們先來看看test命令。test命令的參數是條件判斷式,當 條件為真時則傳回非零值,而條件為偽時則傳回零。在所有的流程式控制制都必須用到 test命令來判斷真偽。而test命令的使用方法則列於附錄B。 

test $# = 0 

如果執行這個程式沒有參數時,會傳回非零值代表"$# = 0"這個條件成立。反 之則會傳回零。 

以下介紹各種流程式控制制: 

1. if then文法以及流程圖如下 

│ FALSE
if (condition) <condition>—┐
then │TRUE │
then-commands then-commands │
fi ├————┘

condition 是一個test命令。往後所介紹的各種流程中的condition 都是test 命令。 
檔名:chkarg 

┌———————————┐
│if (test $# != 0) │
│ then │
│ echo Arg1: $1 │
│fi │
└———————————┘
$ chkarg Hello
Arg1: Hello
$ chkarg
$

2. if then else文法以及流程圖如下 

│ FALSE
if (condition) <condition>—————┐
then │TRUE │
then-commands then-commands else-commands
else ├————————┘
else-commands │
fi

3. if then elif文法以及流程圖如下 

│ FALSE
if (condition1) <condition1>—┐
then │TRUE │ FALSE
commands1 commands1 <condition2>—┐
elif (condition2) │ │ TRUE │
then │ commands2 commands3
commands2 ├—————┴————┘
else │
commands3

commands3
fi

echo 'word 1: \c'
read word1
echo 'word 2: \c'
read word2
echo 'word 3: \c'
read word3
if (test "$word1" = "$word2" -a "$word2" = "$word3")
then
echo 'Match: words 1, 2, & 3'
elif (test "$word1" = "$word2")
then
echo 'Match: words 1 & 2'
elif (test "$word1" = "$word3")
then
echo 'Match: words 1 & 3'
elif (test "$word2" = "$word3")
then
echo 'Match: words 2 & 3'
else
echo 'No match'
fi

4. for in文法以及流程圖如下 

│ FALSE
for var in arg-list ┌—<arg-list還有東西嗎?>—┐
do │ │TRUE │
commands │ 從arg-list取得一項 │
done │ 放到變數var │
│ │ │
│ commands │
└——————┘ │
┌———————————┐ ┌—————┘
│for a in xx yy zz │ │
│ do │
│ echo $a │
│done │
└———————————┘
結果如下:
xx
yy

yy
zz

5. for文法以及流程圖如下 

│ FALSE
for var ┌—<參數中還有東西嗎?>—┐
do │ │TRUE │
commands │ 從參數中取得一項 │
done │ 放到變數var │
│ │ │
│ commands │
└—————┘ │
檔名:lstarg ┌—————┘
┌———————————┐ │
│for a │
│ do │
│ echo $a │
│done │
└———————————┘
$lstarg xx yy zz
xx
yy

yy
zz

6. while 文法以及流程圖如下 

│ FALSE
while (condition) ┌—<condition>—┐
do │ │TRUE │
commands │ commands │
done └————┘ │
┌————┘

┌———————————————┐
│number=0 │
│while (test $number -lt 10) │
│ do │
│ echo "$number\c" │
│ number=`expr $number + 1` │
│done │
│echo │
└———————————————┘
結果如下:
0123456789

7. until文法以及流程圖如下 

│ TRUE
until (condition) ┌—<condition>—┐
do │ │FALSE │
commands │ commands │
done └————┘ │
┌————┘

它和while 的不同只在於while 是在條件為真時執行迴圈,而until 是在條件 為假時執行迴圈。 

8. break及continue 
這兩者是用於for, while, until 等迴圈控制下。break 會跳至done後方執行 ,而continue會跳至done執行,繼續執行迴圈。 

9. case文法以及流程圖如下 

│ TRUE
case str in <str=pat1>————commands1—┐
pat1= commands1;; │FALSE TRUE │
pat2= commands2;; <str=pat2>————commands2—┤
pat3= commands3;; │FALSE TRUE │
esac <str=pat3>————commands3—┤
│FALSE │
├————————————┘

而pat 除了可以指定一些確定的字串,也可以指定字串的集合,如下 
* 任意字串 
? 任意字元 
[abc] a, b, 或c三字元其中之一 
[a-n] 從a到n的任一字元 
| 多重選取 

┌———————————————┐
│echo 'Enter A, B, or C: \c' │
│read letter │
│case $letter in │
│ A|a= echo 'You entered A.';;│
│ B|b= echo 'You entered B.';;│
│ C|c= echo 'You entered C.';;│
│ *= echo 'Not A, B, or C';; │
│esac │
└———————— 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.