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