構建shell基本腳本

構建shell基本腳本

來自專欄 Shell腳本必知必會4 人贊了文章

在前面已經介紹了linux系統和命令行的基礎知識,是時候開始編程了。本節將討論編寫shell腳本的基礎知識,下一節將詳細介紹shell語言的語法知識。在開始編寫自己的shell腳本大作前,首先需要了解一些基本概念。

1. 使用多個命令

到目前為止,已經介紹了如何使用shell命令行界面的提示符輸入命令和查看命令的結果。shell腳本的關鍵在於輸入多個命令並處理每個命令的結果,甚至需要講一個命令的結果傳給另一個命令。shell可以讓你將多個命令串起來,一次執行完成。如果要兩個命令一起運行,可以把它們放在同一行中,彼此間用分號隔開。

例如:用date顯示當前日期,然後用who顯示當前誰在線。

>date;who2018年 6月14日 星期四 22時26分56秒 CSTwan console May 5 18:27 wan ttys000 Jun 14 22:26

這種寫法對於小型腳本尚可,一旦腳本變得複雜,每次都重新敲入整個命令,就顯得耗時而又麻煩。一種簡單的方法是把這些操作寫入文件,每次運行文件即可,這就是使用shell腳本的目的。

2. 創建shell腳本

創建shell腳本,可以使用前面介紹的文件編輯工具vim或gedit。將剛才的多個命令寫入shell腳本如下所示:

#!/bin/bash#用date顯示當前日期,然後用who顯示當前誰在線datewho

我們會發現多了兩個帶井號(#)的行。正常情況下,井號是注釋符,後面的內容代表注釋的內容,但第一行比較特殊,#後面的驚嘆號會告訴shell用哪個shell來運行腳本,在上例中使用的是bash,當然你也可以使用ksh、zsh,根據個人的愛好和用途進行合理選擇。

假設前面的例子保存的文件名為test.sh(一般我們用.sh作為shell腳本的後綴名,方便識別),如果我們直接運行test.sh可能顯示當前命令無法找到的情況,原因在於test.sh文件的路徑並不存在環境變數PATH中,需要把當前路徑添加到環境變數PATH。另一種方式是以./test.sh運行,其中「.」代表當前路徑。

這時可能報另一個錯誤:

>./test.sh-bash: ./test: Permission denied>ls -l-rw-r--r-- 1 wan staff 94 6 14 22:40 test.sh

原因在於沒有給shell腳本賦執行許可權,可以使用chmod命令修改文件的許可權。

>chmod u+x test.sh>./test2018年 6月14日 星期四 22時50分40秒 CSTwan console May 5 18:27 wan ttys000 Jun 14 22:26

3. 顯示消息

用echo命令可以顯示消息,echo的詳細用法之前已有介紹,這裡不再贅述。

對剛才的腳本修改如下:

#!/bin/bash#用date顯示當前日期,然後用who顯示當前誰在線echo -n the time and date are:dateecho "當前誰在線:"who

執行結果:

the time and date are:2018年 6月14日 星期四 22時58分47秒 CST當前誰在線:wan console May 5 18:27 wan ttys000 Jun 14 22:26

echo後面的字元串可以直接賦值,也可以用單引號括起來,或者用雙引號括起來。單引號和雙引號兩者之間的區別在於單引號對於變數無法解析,而雙引號可以。

為了讓列印的字元更符合預期,可以在echo後面加參數,例如「-n」,改變輸出方式。

4. 使用變數

在前面我們介紹過變數分為環境變數和用戶變數,在shell腳本中我們也可以使用,引用一般方式是$變數或者${變數}。

另一種是命令替換,將命令賦給變數。有兩種方式實現:一種是使用「`」符號,該符號位於esc鍵下面,注意和單引號區分;另一種是使用小括弧$(命令)格式。

例如:修改前的腳本如下

#!/bin/bash#用date顯示當前日期,然後用who顯示當前誰在線echo PATH:$PATHvar=testingecho ${var}echo "${var}"cmd=$(date)echo "the time and date are:"$cmd

執行結果:

PATH:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin${var}testingthe time and date are:2018年 6月14日 星期四 23時09分29秒 CST

5. 重定向輸入輸出

有時候你可能需要將輸出的結果不是在顯示器上顯示,而是寫入文件,這時候你需要藉助新的命令進行該操作。bash shell提供了幾個操作符,可以將命令的輸出重定向到另一個位置,比如文件。當然,重定向不僅可以作用於輸出,也可以作用於輸入,接下來將介紹重定向操作符的用法。

5.1 輸出重定向

最基本的重定向操作符是「>」,它的作用是將輸出發送到一個文件中。

例如:將上例中的結果輸出到文件而不是顯示器

> ./test.sh > test.log

另一個重定向輸出操作符是「>>」,它的作用也是將輸出發送到一個文件中。與「>」不同的是,「>>」寫入文件是以追加的形式寫入文件的末尾,而不是先清空,然後再寫入。注意細細區分兩者。

例如:將「hello world」追加到test.log文件末尾

> echo "hello world" >> test.log

5.2 輸入重定向

剛才說了輸出重定向操作符,有輸出必然有輸入。輸入重定向是將文件的內容重定向到命令作為輸入,可以讓數據的讀取方式更為靈活,而不是局限於標準輸入。

基本的輸入重定向操作符是「<」。

例如:使用wc統計test.log的行、詞數和位元組數信息

> wc < test.log 9 34 354

另一種輸入重定向操作符是「<<」,與輸出重定向操作符是「>>」類似,也是起到追加作用,只不過是追加輸入,即命令持續讀取輸入信息,直到遇到「<<」後面的字元然後停止讀取,因此它又被稱作內聯輸入重定向。與「<」的區別是:「<<」命令一般不作用於文件,而是直接作用於標準輸入讀取數據。

例如:使用wc統計標準輸入的行、詞數和位元組數信息

> wc << EOF> test.log> hello world> string> test> EOF 4 5 33

這裡只對重定向操作進行簡單介紹,在後面的章節將詳細闡述重定向操作符使用中遇到的各種奇技淫巧。

6. 管道

有時需要將一個命令的輸出作為另一個命令的輸入,這可以通過重定向進行實現,但是顯得稍微麻煩。另一種簡單的操作是使用管道命令「|」。管道是一種非常有用的技術,常常用於進程間通信,因此需要熟練掌握。

例如:使用管道獲取test.sh執行結果中每一行的前3個字元

> ./test.sh | cut -c1-3the當前誰wanwanPAT${vtesthe

當然,我們也可以使用重定向:

> ./test.sh > test.log> cut -c1-3 < test.logthe當前誰wanwanPAT${vtesthehel

在重定向中需要兩步操作且需要寫入和讀取文件,而管道只需要一步操作,且不需讀寫文件,不僅書寫更為簡潔,而且效率更高,因此對於這種一個命令讀入的是另一個命令的輸出結果,建議採用管道。

7. 數學運算

由於shell默認是對字元串進行操作的,因此如果需要進行數學運算,需要使用expr命令,或者使用$[數學運算]。常見的數學運算有:算術運算加、減、乘、除、取模、取余;邏輯運算與、或;關係運算大於、大於等於、等於、小於等於、小於;查找運算模式匹配。

需要注意的是,expr命令對於詞法分析的功能較弱,一般通過空白字元間隔來區分不同的詞,如果對操作數和操作符不用空白字元隔開,將默認為一個整體。

例如:計算1+3

> expr 1+31+3> expr 1 + 3 4> var=$[1 + 3]> echo $var4

我們知道,計算機對於整型和浮點型的數使用的編碼方法是很不一樣的,詳細參照專欄《python兩三事》中對於數的編碼介紹。在一些高級語言,例如C、java,這些差異操作對用戶是透明的,而在shell中則需要分開處理,對於浮點數的操作需要使用另一個命令bc。bc的功能非常強大,這裡只對它進行舉例,如果想進一步了解可以使用man bc操作了解詳細用法。

例如:計算100/26

> var1=100> var2=26> var3=$(echo "scale=4;$var1 / $var2" | bc)> echo answer is $var3answer is 3.8461

8. 退出腳本

到目前為止,無論是運行命令還是運行shell腳本,我們都沒有對運行結果進行檢查,而在實際中,由於代碼總是存在各種bug,因此需要對一些關鍵點的執行結果進行檢查,以判斷下一步的操作。

8.1 查看退出狀態碼

shell中運行的每個命令都使用退出狀態碼告訴shell它已經運行完畢。退出狀態碼是一個0~255的整數值,在命令結束運行時由命令傳給shell,可以捕獲這個值並在腳本中使用。

例如:捕獲各種執行結果下的退出狀態碼

> date2018年 6月15日 星期五 22時29分09秒 CST> echo $?0>date %tdate: illegal time format>echo $?1> www-bash: www: command not found>echo $?127

8.2 exit命令

有時為了更靈活的捕獲命令執行的結果,我們可以在一些關鍵點設置自己的退出狀態碼。exit命令允許使用者在腳本結束時指定一個退出狀態碼。

例如:修改test.sh的腳本

#!/bin/bashvar1=100.0var2=26var3=$(echo "scale=4;$var1 / $var2" | bc)echo answer is $var3exit 5

然後執行:

> ./test.sh> echo $?5

當前,在這個地方尚且感受不到exit命令的厲害之處,如果和if-then語句結合使用來檢查某個命令返回的錯誤狀態,就能體現它的強大。

推薦閱讀:

【嘎瑪仁波切有聲書】《用好你的富緣》財神是個管道工
溫故之.NET進程間通信——管道
管道的故事(四)
管道支吊架中托架、導向架、支腿、滑托的區別方法
霍尼韋爾新風管道 安裝新風哪種管道好?

TAG:Linux | shell腳本 | 管道 |