天天看點

Shell 程式設計基礎(二)

shift 參數向左移一位

shift + 數字,參數一次向左移N位

程式設計的時候可以用來判斷後面還有幾個參數

當shift後值為空的時候,傳回錯誤

使用read來把輸入值配置設定給一個或多個shell變量

read 從标準輸入中讀取值,給每個單詞配置設定一個變量

所有剩餘單詞都被配置設定給最後一個變量

bash如何展開指令行

按以下優先級順序

把指令行分成單個指令詞

展開别名

展開大括号的聲明({})

展開波浪符聲明(~)

指令替換$() 和 ``

再次把指令行分成指令詞

展開檔案通配(*、 ?、 [abc]等等)

準備I/0重導向(<、 >)

運作指令

轉義

反斜線(\)會使随後的字元按原意解釋

$ echo Your cost: \$5.00

Your cost: $5.00

加引号來防止擴充

• 單引号(’)防止所有擴充

• 雙引号(”)也防止所有擴充,但是以下情況例外:

$(美元符号) - 變量擴充

`(反引号) - 指令替換

\(反斜線) - 禁止單個字元擴充

!(歎号) - 曆史指令替換

環境配置相關

bash的配置檔案

按生效範圍劃分,存在兩類:

全局配置:

/etc/profile

/etc/profile.d/*.sh

/etc/bashrc

個人配置:

~/.bash_profile

~/.bashrc

配置檔案的生效順序與範圍

互動式登入:

(1)直接通過終端輸入賬号密碼登入

(2)使用“ su - UserName” 切換的使用者

執行順序:/etc/profile --> /etc/profile.d/*.sh -->~/.bash_profile --> ~/.bashrc --> /etc/bashrc

 非互動式登入:

(1)su UserName

(2)圖形界面下打開的終端

(3)執行腳本

(4)任何其它的bash執行個體

執行順序: ~/.bashrc --> /etc/bashrc -->/etc/profile.d/*.sh

Profile類

 按功能劃分,存在兩類:

profile類和bashrc類

 profile類:為互動式登入的shell提供配置

全局:/etc/profile, /etc/profile.d/*.sh

個人:~/.bash_profile

功用:

(1) 用于定義環境變量

(2) 運作指令或腳本

bashrc類

 bashrc類:為非互動式和互動式登入的shell提供配置

全局:/etc/bashrc

個人:~/.bashrc

(1) 定義指令别名和函數

(2) 定義本地變量

編輯配置檔案生效

 修改profile和bashrc檔案後需生效

兩種方法:

1重新啟動shell程序

2 . 或source

例:

. ~/.bashrc

bash 退出任務

 儲存在~/.bash_logout檔案中(使用者)

 在登出shell時運作

 用于

建立自動備份

清除臨時檔案

$-變量

 h:hashall,打開這個選項後,Shell 會将指令所在的路徑hash下來,避免每次都要查詢。通過set +h将h選項關閉

 i:interactive-comments,包含這個選項說明目前的 shell是一個互動式的 shell。所謂的互動式shell,在腳本中,i選項是關閉的。

 m:monitor,打開監控模式,就可以通過Job control來控制

程序的停止、繼續,背景或者前台執行等。

 B:braceexpand,大括号擴充

 H:history,H選項打開,可以展開曆史清單中的指令,可以

通過!感歎号來完成,例如“!!”傳回上最近的一個曆史指令,

“!n”傳回第 n 個曆史指令

$* 與$@的差別

$*

以下是a.sh的腳本代碼:

以下是b.sh的腳本代碼

看到了吧,$*把所有參數當成了一個整體,是以b.sh的第一個參數就是a b c,後面的參數就是為空了

$@

由于跟以上示範隻是相差了一點,将b.sh調用變成$@

看到了吧,$@把所有參數當成了獨立的個體,是以b.sh的各個參數就是a.sh一樣了。

shift作用示範

以下為腳本内容:

echo "這個腳本的名字是:`basename $0`"

echo "第一個參數是:$1"

echo "第二個參數是:$2"

echo "第三個參數是:$3"

echo "示範下shift參數調整功能,這裡隻是一次一個,shift後面可以接具體數字的"

shift

echo "第一個參數是原來的\$2參數:$1"

echo "第二個參數是原來的\$3參數:$2"

echo "第三個參數是原來的\$3之後的參數,因為是沒有,應該是空的:$3"

邏輯運算

true =1    false =0

與運算

1與1 為1

隻要有0就為0

或運算

隻要有1就為1

0與0 為0

! 0 為1

! 1 為 0

shell程式設計中的短路運算

短路與

第一個為0,結果必定為0

第一個為1,第二個必須要參與運算

比如:

指令1 && 指令2

當指令1傳回值為0,也就是真的時候,指令2必須參與運算

當指令1傳回值為1,也就是假的時候,指令2不會參與運算

短路或

第一個為1,結果必定為1

第一個為0,第二個必須要參與運算

指令1 || 指令2

當指令1傳回值為1,也就是假的時候,指令2必須參與運算

當指令1傳回值為0,也就是真的時候,指令2不會參與運算

異或:^

異或的兩個值,相同為假,不同為真

指令1 ^ 指令2

當指令1和指令2傳回值都相同的時候,得出的就是假

當指令1和指令2傳回值不相同的時候,得出的就是真

看以下例子,操作符位置不一樣,結果就不一樣了,為什麼第一條會同時顯示2條資訊呢?

第一條指令集傳回狀态是這麼解讀的:第一條指令查找不到使用者,傳回值為非0,假,是以将會執行||這後的指令并且輸出成功,傳回值為0,真,是以就會執行&&之後的指令,并且成功輸出并且傳回值為0.

是以會顯示出2條資訊。

第二條指令集傳回狀态是這麼解讀的:第一條指令查找不到使用者,傳回值為非0,假,與後面是與的關系,後面不管是真假,最終的結果都是假了,是以會執行||之後的指令并且輸出成功,傳回值為0

下圖我們故意把echo輸入錯誤,變成echoa,這樣,這一條指令就會傳回為非0,假

指令集傳回狀态是這麼解讀的:第一條指令查找到使用者,傳回值為0,真,是以會執行後面的指令,可是後面的指令是錯誤的指令,會傳回非0,假,與後面的指令是或的關系,它必須執行,輸出成功,傳回值為0

特殊運算結果産生的坑

expr 和let指令計算的時候,要注意

expr 計算的結果是null或0的時候,$?傳回的值為1

let計算的時候,最後一個參數為0的時候,傳回值為1

中括号可以用來判斷變量是否為空,請仔細觀察以下變化。中括号内的變量記得用雙引号

也可以使用一個字元+變量來組合判斷變量是否會空

雙中括号裡一些使用規範

[[  "$var" == "abc"  ]]   判斷2邊字元串是否相等時,使用==

[[  "$var" =~ \.sh$  ]]   當使用=~擴充正規表達式時,表達式不需要帶引号

如果是在比較字元串的時候,==後面加引号表過的是字元串,不加引号表示的是通配符,是以,這種情況比較容易搞蒙自己。那麼建議是這樣的:隻有涉及到需要使用正規表達式的時候才使用雙括号。

BUG

以下是bash的一個BUG了哦,隻要在正規表達式裡面出現了反斜線,就會導緻比對失敗,是以,解決方案就是把正規表達式内容用變量代替。

以下是2個不同的案例對比

來個簡單點的正則吧

測試條件時

-v 變量名  檢查變量是否已經設定

Centos 6 是不支援 -v 的

num="";[ -v num  ] && echo "設定" || echo "未設定"

Centos 7

分組

linux中shell的小括号、大括号的用法差別

小括号()

①指令組。括号中的指令新開一個子shell程式,括号中的變量為本地變量 ,不能夠在腳本其他部分使用。括号中多個指令之間用分号隔開。

②指令替換。指令替換$(cmd)等同于`cmd`(這不是單引号,`是ESC下面的那個鍵) ,shell執行過程中發現了$(cmd)結構,便将$(cmd)中的cmd執行一次,得到其輸出,再将此輸出放到原來指令。例如:

這是一個執行個體,如果沒有加上小括号的時候,cd /app/dir/ 後,再執行pwd可以看到确實是進入了目錄,但是當括号内的pwd指令執行完之後,指令提示符顯示的就是/app,也就是cd指令前的目錄。因為cd指令是作用在子程序了。在實際中的應用場景的話,就是臨時開啟一個子程序執行一些操作而不影響目前環境

③用于初始化數組。如:arr=(m n)

大括号 {  }

①拓展。對大括号中的檔案名做擴充。在大括号中,不允許有空白,除非這個空白被引用或轉義。拓展分為普通以逗号(,)進行拓展,如echo {a,b}.txt将間隔的各項内容均列出;以兩個點(..)進行拓展,如echo {1..5}.txt自動補全1到5中間内容。

# echo {a,b}.txt

a.txt b.txt

# echo {1..5}.txt

1.txt 2.txt 3.txt 4.txt 5.txt

②内部組 。與小括号中的指令不同,大括号内的指令在目前shell運作,不會重新開子shell。括号内的指令間用分号隔開,最後一個指令後必須跟分号。{}的第一個指令和左括号之間必須要有一個空格。

在Shell中的小括号,大括号結構和有括号的變量,指令的用法如下:

1.${var}

2.$(cmd)

3.()和{}

4.${var:-string},${var:+string},${var:=string},${var:?string}

5.$((exp))

6.$(var%pattern),$(var%%pattern),$(var#pattern),$(var##pattern)

現在來一一詳細介紹:

1)Shell中變量的原形

這個最常見的變量形式就是$var,列印var用指令

echo $var

可是這裡有個問題:當你要顯示變量值加随意的字元(如$varAA)時,就會出錯。系統會認為整個varAA是一個變量,這時就可以用一個大括号來限定變量名稱的範圍,如${var}AA,這樣就好了。

此時正是使用 {大括号} 的時候了

2)指令替換$(cmd)

指令替換$(cmd)和符号`cmd`(注意這不是單引号,在美式鍵盤上,`是ESC下面的那個鍵)有相同之處.以echo$(ls)來說明整個替換過程:shell掃描一遍指令行,發現了$(cmd)結構,便将$(cmd)中的cmd執行一次,得到其标準輸出,再将此輸出放到原來指令echo $(ls)中的$(ls)位置,即替換了$(ls),再執行echo指令。如下:

3)一串的指令執行()和{}

()和{}都是對一串的指令進行執行,但有所差別:

A, ()隻是對一串指令重新開一個子shell進行執行

B, {}對一串指令在目前shell執行

C, ()和{}都是把一串的指令放在括号裡面,并且指令之間用;号隔開

D, ()最後一個指令可以不用分号

E, {}最後一個指令要用分号

F, {}的第一個指令和左括号之間必須要有一個空格

G, ()裡的各指令不必和括号有空格

H, ()和{}中括号裡面的某個指令的重定向隻影響該指令,但括号外的重定向則影響到括号裡的所有 指令

本文轉自 ljpwinxp 51CTO部落格,原文連結:http://blog.51cto.com/191226139/2054749

繼續閱讀