6.1 shell指令碼基礎-bash變數和邏輯執行
bash特性及bash指令碼程式設計初步
終端,附著在終端的介面程式
GUI:KDE,GNome,Xfce
CIT:/etc/shells
bash
zsh
fish
bash的特性:
命令列展開:-,{}
命令別名:alias,unalias
命令歷史:history
檔名通配:glob
快捷鍵:Ctrl+a,e,u,k,l
命令補全:$PATH
路徑補全:
bash特性之:命令hash
快取此前命令的查詢結果:key-value
key:搜尋鍵
value:值
hash:列出
hash -d command:刪除某個命令快取結果
hash -r:清空雜湊表
bash的特性之:變數
程式:指令+資料
指令:由程式檔案提供
資料:IO裝置、檔案、管道、變數
程式:演算法+資料結構
變數名+指向的記憶體空間
變數賦值:name=value
變數型別:儲存格式、表示資料範圍、參與的運算
程式語言:
強型別變數
弱型別變數:
bash把所有變數統統視作字元型
bash不支援浮點資料,除非藉助外界工具來進行
bash中的變數無需事先宣告:相當於,把宣告和賦值過程同時實現
宣告:型別、變數名
變數替換:把變數名出現的位置替換為其所指向的記憶體空間中的資料
變數引用:${var_name},
變數名:變數名只能包含數字、字母和下劃線,而且不能以數字開頭
變數名:見名之義,命名機制遵循某種法則;不能夠使用程式的保留字,例如if,else,then,while等等
bash變數型別:
本地變數:作用範圍僅為當前shell程序
環境變數:作用範圍為當前shell程序及子程序
區域性變數:作用範圍僅為某程式碼片段(函式上下文)
位置引數變數:向執行指令碼的shell程序傳遞的引數
特殊變數:shell內建的有特殊功用的變數
$?:
0:成功
1-255:失敗
本地變數:
變數賦值:name=value
變數引用:${name},$name
" ":變數名會替換為其值
' ':變數名不會替換為其值
檢視變數:set命令
撤銷變數:unset name
注意:此處非變數引用,不能用$符
環境變數:
變數賦值:
(1)export name=value
(2)name=value
export name
(3)declare -x name=value
(4)name=value
declare -x name
變數引用:${name},$name
注意:bash內嵌了許多環境變數(通常為全大寫字元),用於定義bash的工作環境
PATH,HISTFILE,HISTSIZE,HISTFILESIZE,SHELL,HOME,UID,PWD,OLDPWD
檢視環境變數:export、declare -x,printenv,env
撤銷環境變數:unset name
只讀變數:
(1)declare -r name
(1)readonly name
只讀變數無法重新賦值,並且不支援撤銷;存活時間為當前shell程序的生命週期,隨shell程序終止而終止
bash特性之多命令執行:
~]# command1,;command2;command3;...
邏輯運算:
運算數:真(true,yes,on,1)
假(false,no,off,0)
與:
1 && 1 = 1
1 && 0 = 0
0 && 1 = 0
0 && 0 = 0
或:
1 | | 1 = 1
1 | | 0 = 1
0 | | 1 = 1
0 | | 0 = 0
非:
!1 = 0
!0 = 1
短路法則:
~]# command1 && command2
command1為“假”,則command2不會再執行
否則,command為“真”,則command2必須執行
~]# command1 | | comman2
command1為“真”,則command2不會再執行
否則,command1為“假”,則command2必須執行
示例:id user1 || useradd user1
shell指令碼程式設計:
程式語言的分類:根據其執行方式
編譯執行:原始碼 --> 編譯器(編譯) --> 程式檔案
解釋執行:原始碼 --> 執行時啟動直譯器,由直譯器邊解釋邊執行
根據其程式設計過程中功能的實現是呼叫庫還是呼叫外部的程式檔案:
shell指令碼程式設計:
利用系統上的命令及程式設計元件進行程式設計
完整程式設計:
利用庫或程式設計元件進行程式設計
程式設計模型:程序式程式設計語言,面向物件的程式語言
程式=指令+資料
過程式:以指令為中心來組織程式碼,資料是服務於程式碼
順序執行
選擇執行
迴圈執行
代表:C,bash
物件式:以資料為中心來組織程式碼,圍繞資料來組織指令
代表:Java,C++,python
shell指令碼程式設計:程序式程式設計,解釋執行,依賴於外部程式檔案執行
如何寫shell指令碼:
指令碼檔案的第一行,頂格:給出shebang,直譯器路徑,用於指明解釋執行當前指令碼的直譯器程式檔案
常見的直譯器:
#!/bin/bash
#!/uer/bin/python
#!/usr/bin/perl
文字編輯器:nano
行編輯器:sed
全螢幕編輯器:nano,vi,vim
shell指令碼是什麼?
命令的堆積;
但很多命令不具有冪等性,需要用程式邏輯來判斷執行條件是否滿足,以避免其執行中發生錯誤
執行指令碼:
(1)賦予執行許可權,並直接執行此程式檔案
chmod +x /PATH/TO/SCRIPT_FILE
/PATH/TO/SCRIPT_FILE
(2)直接執行直譯器,將指令碼以命令列引數傳遞給直譯器程式
bash /PATH/TO/SCRIPT_FILE
注意:指令碼中的空白行會被直譯器忽略
指令碼中,除了shebang,餘下所有以#開頭的行,都會被視作註釋行而被忽略,此即為註釋行
shell指令碼的執行是通過執行一個子shell程序實現的
練習1:寫一個指令碼,實現如下功能:
(1)顯示/etc目錄下所有以大寫p或小寫p開頭的檔案或目錄本身
(2)顯示/var目錄下的所有檔案或目錄本身,並將顯示結果中的小寫字母轉換為大寫後顯示
(3)建立臨時檔案/tmp/myfile.XXXXX
#!/bin/bash
ls -d /etc/[pP]*
ls -d /var/* | tr "a-z" "A-Z"
mktemp /tmp/myfile.XXXXX
bash的配置檔案:
兩類:
profile類:為互動式登入的shell程序提供配置
bashrc類:為非互動式登入的shell程序提供配置
登入型別:
互動式登入shell程序:
直接通過某終端輸入賬號和密碼後登入開啟的shell程序
使用su命令:su - username,或者使用 su - l username執行的登入切換
非互動式登入shell程序:
su username執行的登入切換
圖形介面下開啟的終端
執行指令碼
profile類:
全域性:對所有使用者都生效
/etc/profile
/etc/profile.d/*.sh
使用者個人:僅對當前使用者有效
~/.bash_profile
功用:
1.用於定義環境變數
2.執行命令或指令碼
bashrc類:
全域性:
/etc/bashrc
使用者個人:
~/.bashrc
功用:
1.定義本地變數
2.定義命令別名
注意:僅管理員可修改全域性配置檔案
互動式登入shell程序:
/etc/profile --> /etc/profile.d/* --> ~/.bash_profile --> ~/.bashrc -- /etc/bashrc
非互動式登入shell程序:
~/.bashrc --> /etc/bashrc --> /etc/profile.d/*
命令列中定義的特性:例如變數和別名作用域為當前shell程序的生命週期
配置檔案定義的特性,只對隨後新啟動的shell程序有效
讓通過配置檔案的特性立即生效:
(1)通過命令列重新定義一次
(2)讓shell程序重讀配置檔案
~]# source /PATH/FROM/CONF_FILE
~]# . /PATH/FROM/CONF_FILE
問題1:定義對所有使用者都生效的命令別名,例如“lftps="lftp 172.16.0.1/pub"”
問題2:讓centos使用者登入時,提供其已經登入,並顯示當前系統時間?