Linux之shell編程入門

shell編程

1.什麼是shell?

Shell是一種編程語言, 它像其它編程語言如: C, Java, Python等一樣也有變量/函數/運算符/if語句/循環控制/… 但在開始之前, 我想先理清Shell語言與Shell之間的關係.

當命令不在命令行中執行,而是從一個文件中執行時,該文件就是shell腳本。

Shell是一種解釋型編程語言,不需要編譯,執行時也是按行執行。

Shell腳本是由解釋器解釋執行的,常見的解釋器有:bash dash ash ksh sh等

特點:

shell腳本是普通的文本文件,由流程控制邏輯和命令構成。

shell腳本通常以.sh作為後綴名,但不是必須的。

我們現階段學習的主要是bash dash.

2.shell腳本的編制、執行和調試

創建第一個shell腳本文件

#! /bin/sh

echo "hello shell!"

在shell編程中,通常情況下,#代表註釋,但是第一行的#是一個特例。

Linux之shell編程入門

Linux之shell編程入門

此時報錯是因為文件並沒有可執行權限,所以報了 Permission denied 錯誤。

報錯原因:

根據下面截圖我們也可以看出,HelloWorld.sh的文字顏色是白色,並不是綠色,所以也可以看出它並沒有執行權限。再者,當前我們使用的是root用戶,該用戶並沒有x權限,因此我們要賦權限, 可以使用 chmod 775 HelloWorld.sh命令或者chmod u+x HelloWorld.sh命令來賦權限。

Linux之shell編程入門

其實運行shell程序共有三種方法,除了給文件賦予可執行權限外,還有另外兩種方法。

1. chmod +x使文件具有可執行權限, 直接運行

2. 直接調用解釋器, 將腳本文件作為參數傳入 (比如bash hi.sh)

3. 使用source(也可用 . 代替)執行文件

通常情況下, 最方便的方式就是方式1, 通過方式1執行你需要在腳本第一行寫好這段腳本由哪個解釋器來解釋, 而通過方式2來執行則沒有這個限制, 寫了也沒用. 除此之外方式1與方式2執行命令就沒有區別了, 但方式3執行的方式與前兩種都不同:

使用source執行shell腳本時, 不會創建子進程, 而是在父進程中直接執行!

3.變量 $

shell中沒有變量類型,本質上都是字符串

特點:

1. Shell中的變量只有字符串這一種類型

2. Shell中變量名與變量值沒有長度限制

3. Shell的變量也允許比較操作和整數操作, 只要變量中的字符串為數字

shell中有四種類型的變量

本地變量:僅在當前shell中有用,在shell外部或者子shell中都不可用

環境變量:當前及子shell有用

位置參數變量:腳本的參數或者函數的參數等

特殊變量:腳本內置的具有特殊用途的變量

Linux之shell編程入門

Linux之shell編程入門

位置參數變量

  • 是一組特殊的內置變量跟在腳本名後面的用空格隔開的每個字符串

$1 表示第1個參數值,……,$9 表示第9個參數值

${10} 表示第10個參數值, ${11} 表示第11個參數值, ……

  • 位置參數的用途

  • 從 shell 命令/腳本 的命令行接受參數

  • 在調用 shell 函數時為其傳遞參數

  • $#代表所有參數的總數。

Linux之shell編程入門

特殊變量

  • 命令行參數相關

$* 將所有位置參量看成一個字符串(以空格間隔) 。

$@ 將每個位置參量看成單獨的字符串(以空格間隔)。

"$*" 將所有位置參量看成一個字符串(以$IFS間隔)。

"$@" 將每個位置參量看成單獨的字符串(以空格間隔) 。

$0 命令行上輸入的Shell程序名。

$# 表示命令行上參數的個數。

  • 進程狀態相關

$? 表示上一條命令執行後的返回值

$$ 當前進程的進程號

$! 顯示運行在後臺的最後一個作業的 PID

$_ 在此之前執行的命令或腳本的最後一個參數

Linux之shell編程入門

4.流程控制和循環

if判斷

格式:

if condition

then

do something

elif condition

then

do something

elif condition

then

do something

else

do something

fi

if判斷中 if後用中括號[] 並且要特別注意空格, [ ] 兩邊一定要加空格, 結尾用fi

測試截圖如下:

Linux之shell編程入門

Linux之shell編程入門

其中, elif語句和else語句非必須的.看個例子:

For循環

基本結構:

for name [in list]

do

...

done

其中,[]括起來的 in list, 為可選部分, 如果省略in list則默認為in "$@", 即你執行此命令時傳入的參數列表.

舉例如下圖:

For循環腳本內容:

Linux之shell編程入門

執行結果:

Linux之shell編程入門

while循環

基本結構:

while condition

do

do something...

done

看個例子:

#! /bin/sh

i=0

while ((i<5));

do

((i++))

echo "i=$i"

done

輸出:

i=1

i=2

i=3

i=4

i=5

NOTE: 你可能需要去了解一下(())的用法

until循環

基本結構

until condition

do

do something...

done

看個例子:

#! /bin/sh

i=5

until ((i==0))

do

((i--))

echo "i=$i"

done

輸出:

i=4

i=3

i=2

i=1

i=0

跳出循環

shell中也支持break跳出循環, continue跳出本次循環.用法與C, Java中相同

5.退出/返回狀態

$?:返回上一條語句或腳本執行的狀態

0:成功

1-255:不成功

exit 命令

例如: exit n

exit 命令用於退出腳本或當前Shell

n 是一個從 0 到 255 的整數

0 表示成功退出,非零表示遇到某種失敗

返回值 被保存在狀態變量 $? 中

常見的返回狀態碼

0:

執行正確

1:

通用錯誤

126:

命令或腳本沒有執行權限

127:

命令沒找到

6.數據流重定向

標準輸入:代碼0,使用 < 或者 <<

標準輸出:代碼1,使用 > 或者 >>

錯誤輸出:代碼2,使用 > 或者 >>

> 表示 寫入; >>表示追加

舉例:

往hosts文件裡追加兩行域名的解析

創建updateHost.sh文件 編寫腳本語言,將特定內容自動寫入指定文件中。

Linux之shell編程入門

執行腳本文件

Linux之shell編程入門

查看(寫入成功)

Linux之shell編程入門

7.命令的連續執行 && ||

腳本中經常有多條相關命令,比如:

執行備份日誌成功後刪除日誌

從服務器下載文件失敗後從備份服務器下載

&& 連起來的命令,後面的命令只有在前一命令執行成功後才執行

|| 連起來的命令,後面的命令只有在前一命令執行失敗後才執行

從服務器下載文件失敗後從備份服務器下載

#!/bin/sh

master_ip="172.172.172.172" #主服務器IP地址變量

bak_ip="172.172.172.182"#備份服務器IP地址變量

url="/downloads/?id=1800"#要下載的文件

curl -O "http://${master_ip}${url}" || curl -O "http://${bak_ip}${url}

命令的連接 | (管道符號)

8.awk——命令連接常用命令

簡介:

awk是一個非常棒的數據處理程序,它比較傾向於將一行分成多個'字段'來處理。

數據可以來自標準輸入、一個或者多個文件、其他進程的輸出

awk從第1行到最後一行逐行掃描,並執行匹配的操作

awk的默認操作是輸出匹配行即打印匹配行到標準輸出

awk語法:

awk 'BEGIN{語句1;語句2;...} END{語句1;語句2;...} 模式1{語句1;語句2;...} 模式2{語句1;語句2;...} 模式n...' [文件名]

如果沒有文件名,則數據來自標準輸入

BEGIN{...} 是awk開始運作前執行的語句;END{...}是awk最終結束後執行的語句,他們可以省略

awk默認分隔符是空格和tab,可以在BEGIN語句中為FS內置變量賦值重新定義分隔符

舉例:

awk 'BEGIN{print "awk start..."} END{print "awk end."} {print "awk programmer"}' /etc/profile

awk '{print $0}' /etc/profile #$0代表一整行數據,數據來自文件

echo "1 2 3 4" | awk '{print $1$4}' #$1代表第1列,$4代表第4列

echo "1 2 3 4" | awk '{print $1A$4}' #中間加入的字符A並不能輸出

echo "1 2 3 4" | awk '{print "$1A$4"}' #參數變量不能加入雙引號

echo "1 2 3 4" | awk '{print $1"A"$4}' #正確方式

echo "1 2 3 4" | awk '{print $1,"A",$4}' #注意與上式比較

注意單雙引號的使用!

適用情景:當我們只想得到某一指定位置的數據時,使用awk我們可以實現。

舉例1:

使用ps -ef | grep tomcat | grep -v grep | awk '{print $2}' 命令 可以查出並只顯示tomcat的進程號(注意單雙引號的使用):

Linux之shell編程入門

案例:根據進程號Kill掉tomcat程序

Linux之shell編程入門

執行該shell文件,則tomcat進程被殺死。

Linux之shell編程入門

PS(shell中的時間格式轉換)

獲得當天的日期

date

獲取明天的日期

date -d next-day +%Y%m%d

獲取昨天的日期

date -d last-day +%Y%m%d

獲取上個月的年和月

date -d last-month +%Y%m

獲取下個月的年和月date -d next-month +%Y%m

獲取明年的年份date -d next-year +%Y


分享到:


相關文章: