shell腳本編程
shell腳本是包含一些命令或聲明,并符合一定格式的文本文件
shell腳本的用途有:
-
自動化常用命令
-
執行系統管理和故障排除
-
創建簡單的應用程序
-
處理文本或文件
命令查詢過程:別名–>內部變量–>hash–>$PATH
~]#bash -n 檢測腳本語法錯誤
~]#bash -x 順序檢查調試執行
程序的組成:指令+數據 程序編程風格: 1、過程式:以指令為中心,數據服務于指令 2、對象式:以數據為中心,指令服務于數據
編程邏輯處理方式:順序執行、循環執行、選擇執行
變量
什么是變量:是一段命名的內存空間
變量數據類型: 1、字符型 2、數值:整型,浮點型
如何創建shell腳本
使用文本編輯器來創建文本文件 第一行必須包括shell聲明序列:#!/bin/bash 可以自行添加注釋,注釋以#開頭
運行腳本,給予執行權限,在命令行上指定腳本的絕對或相對路徑,直接運行解釋器,將腳本作為解釋器程序的參數運行
編程程序語言分類
強類型:
定義變量時必須指定類型、參與運算必須符合類型要求;調用未聲明變量會產生錯誤
弱類型
無須指定類型,默認均為字符類型;參與運算會自動進行隱式類型轉換;變量無須事先定義可直接調用
編程語言變量命名法則:
不能使用程序中的保留字:例如if、for
只能使用數字、字母及下劃線,且不能以數字開頭
見名知義
統一命名規則:駝峰命名法
Bash中變量的種類
根據變量的生效范圍等標準分:
本地變量:生效范圍為當前shell進程;對當前shell之外的其他shell進程,包括當前shell子shell進程均無效
環境變量:生效范圍為當前shell進程及其子進程
局部變量:生效范圍為當前shell進程某代碼片段(通常指函數)
位置變量:$1,$2,…來表示,用于讓腳本在腳本代碼中調用通過命令行傳遞給它的參數
特殊變量:$?,$0,$*,$@,$#
本地變量:
變量賦值:name='value' 變量引用:name="$USER" 變量引用可分為兩種 "":弱引用,其中的變量引用會被替換為變量值 '':強引用,其中的變量引用不會被替換為變量值,而保持原字符串 命令引用:name=`COMMAND`,name=$(COMMAND) 顯示已定義的所有變量:set 刪除定義的變量:unset name
環境變量
環境變量聲明、賦值 export name=value declare -x name=value 變量引用方式:$name,${name} 顯示所有環境變量:export、env、printenv 刪除變量:unset name Bash有許多內建的環境變量: PATH:可執行文件的搜索路徑,決定了shell將到哪些目錄中尋找命令或程序。 SHELL:當前登錄用戶shell類型 USER:當前登錄用戶 UID:當前登錄用戶ID HISTSIZE:歷史命令記錄數,定義了history命令輸出的記錄數,即輸出.bash_history文件中的最后HISTSIZE行 HISTFILESIZE:定義了在~/.bash_history中保存命令的記錄總數 HISTFILE:歷史命令記錄的配置文件,它是隱藏文件 HOME:當前用戶主目錄 PWD:當前工作目錄 OLDPWD:之前工作目錄 PS1:一級命令提示符 PS2:使用轉義字符,第二行出現的提示符
只讀變量
語法:readonly (option)(arguments) readonly命令用于定義只讀shell變量和shell函數,只能聲明,不能刪除和修改。 ~]#readonly -p 輸出顯示系統中所有定義的只讀變量 -f 定義只讀函數 -a 定義只讀數組變量 變量定義:readonly name declare -r name 注意:只對當前shell有效,注銷后清除
位置變量
在腳本代碼中調用通過命令行傳遞給腳本的參數: $1,$2,...:對應第1、第位參數,shift[n]換位置 $0 命令本身 $* 傳遞給腳本的所有參數。全部參數合為一個字符串 $@:傳遞給腳本的所有參數,每個參數為獨立字符串 $#:傳遞到腳本的參數的個數 $$:腳本運行的當前進程ID號 注意:$@,$*只在被雙引號引起來的時候才會有差異 雙引號括起來的情況:$*將所有的參數認為是一個字段,所有的位置參數,被作為一個單詞 $@每個參數都是一個獨立的""引用字串,這就意味著參數被完整地傳遞,并沒有被解釋和擴展,這也意味著,每個參數列表中的每個參數都被當成一個獨立的單詞.
示例:抄的還請見諒。
#!/bin/bash echo "-------------ISF is set to \"-seperator\" ------------" IFS="-seperator"; # 注意 seperator前有一個減號(-) for i in "$@"; do echo "@ '$i'"; done for i in "$*"; do echo "* '$i'"; done echo "-------------ISF is set to null ------------------------" IFS= for i in "$@"; do echo "@ '$i'"; done for i in "$*"; do echo "* '$i'"; done echo "-------------ISF is unset ------------------------" unset IFS for i in "$@"; do echo "@ '$i'"; done for i in "$*"; do echo "* '$i'"; done echo "---------$* and $@ are not put into double quotes(\"\")-------" for i in $@; do echo "@ '$i'"; done for i in $*; do echo "* '$i'"; done 運行結果: -------------ISF is set to "-seperator" ------------ @ '1' @ '2' @ '3' * '1-2-3' -------------ISF is set to null ------------------------ @ '1' @ '2' @ '3' * '123' -------------ISF is unset ------------------------ @ '1' @ '2' @ '3' * '1 2 3' ---------1 2 3 and 1 2 3 are not put into double quotes("")------- @ '1' @ '2' @ '3' * '1' * '2' * '3'
由此可見, 當不加雙引號("")時, $*,$@被展開時的行為是一樣的; 當$*,$@都被放到雙引號("")內;如果設置了變量IFS的值并且該值非空, 則$*被展開時使用${IFS}的第一個字符將所有參數(除了參數$0)連接起來, 即"$1c$2c$3c...",其中c表示${IFS}的第一個字符; 如果變量IFS為空,則$*被展開時只是將所有參數(除了參數$0)簡單連接起來, 即 “$1$2$3..." 如果變量IFS沒有被定義,則$*被展開時使用空格字符將所有參數(除了參數$0) 連接起來, 即"$1 $2 $3 ..." 但$@的展開和沒有加雙引號的情形是一致的。
算術運算
bash中的算術運算: expr,let +,-,*,/,%取模(取余),**(乘方)
實現算術運算
let var=算術表達式
var=$[算術表達式]
var=$((算術表達式))
var=$(expr arg1 arg2 arg3 …)
declare -i var = 數值
echo '算術表達式' | bc
bash中有內建的隨機數生成器:$RANDOM(1-32767) 示例:echo $[$RANDOM%50]:0-49之間隨機數 expr 作乘法運算的時候需把*轉義\*
賦值
增強型賦值型 +=,-=,*=,/=,%= let varvalue 示例:let count+=3 自加3后在賦值 自增,自減: let var+=1 let var++ let var-=1 let var--1
邏輯運算
true 為1 false 為0 與(and) & 1 與 1 = 1 1 與 0 = 0 0 與 1 = 0 0 與 0 = 0 或(or) | 1 或 1 = 1 1 或 0 = 1 0 或 1 = 1 0 或 0 = 0 非!:! 1 = 0 ! 0 = 1 異或^ 異或的兩個值,相同為假,不同為真 短路運算 短路與 && 第一個為0,第二個必須要參與運算 第一個為1,結果必為1 短路或 || 第一個為1,第二個必須要參與運算 第一個為0,結果必為0 注意:可以說短路運算只能操作布爾型的,而非短路運算不僅可以操作布爾型,而且可以操作數值型。
聚齊命令
有兩種聚集命令的方法 復合式:date;who | wc -l 命令會一個接一個地運行 子shell式:(date;who) | wc -l >>/tmp/trace 所有的輸出都被發送給單個STDOUT和STDERR 作為一個整體
退出狀態
進程使用退出狀態來報告成功或失敗 0 代表成功,1-255代表失敗 $?特殊變量保存最近的命令退出狀態 0 成功退出 >0 退出失敗 1-125 命令退出失敗,失敗返回的相關值由程序定義(譬如,程序內退出只執行 exit 2,則返回為2) 126 命令找到了,但無法執行 127 命令找不到 >128 命令因受到信號而死亡 退出狀態碼 可以bash自定義退出狀態碼 exit [n]:自定義退出狀態碼 注意:腳本中一旦遇到exit命令,腳本會立即終止;終止退出狀態取決于exit命令后面的數字 如果未給腳本指定退出狀態碼,整個腳本的退出狀態碼取決于腳本中執行的最后一條命令的狀態碼
ping -W(設置響應時間)
腳本中添加(置于子shell下)相當于調用一個shell腳本
條件測試
判斷某需求是否滿足,需要由測試機制來實現,專用的測試表達式需要由測試命令輔助完成測試過程。 評估布爾聲明,以便用在條件性執行中 若真,則返回0 若假,則返回1測試命令 test expression(表達式) [ expression ] [[ expression ]] 注意:expression前后必須有空白字符 根據退出狀態而定,命令可以有條件地進行 && 代表條件性的AND THEN || 代表條件下的or else
Bash的測試類型
數值測試: -gt:是否大于 -ge:是否大于等于 -eq:是否等于 -ne:是否不等于 -lt:是否小于 -le:是否小于等于字符串測試: ==:是否等于 >:ascii碼是否大于ascii碼 <:是否小于 !=:是否不等于 =~:左側字符串是否能夠被右側的pattern所匹配 注意:此表達式一般用于[[ ]]中; -z "STRING":字符串是否為空,空為真,不空為假 -n "STRING":字符串是否不空,不空為真,空為假 注意:用于字符串比較時用到的操作數都應該使用引號
文件測試:
存在性測試
-a file: 同-e -e file:文件存在性測試,存在為真,否則為假
存在性及類別測試
-b file:是否存在且為塊設備文件 -c file:是否存在且為字符設備文件 -d file:是否存在且為目錄文件 -f file:是否存在且為普通文件 -h file 或 -L file:存在且為符號鏈接文件 -p file 是否存在且為命名管道文件 -S file 是否存在且為套接字文件
文件權限測試:
-r file:是否存在且可讀 -w file:是否存在且可寫 -x file:是否存在且可執行
文件特殊權限測試:
-g file:是否存在且擁有sgid權限 -u file:是否存在且擁有suid權限 -k file:是否存在且擁有sticky權限
文件大小測試:
-s file:是否存在且非空
文件是否打開:
-t fd:fd表示文件描述符是否已經打開且與某終端相關 -N file:文件自動與上一次被讀取之后是否被修改過 -O file:當前有效用戶是否為文件屬主 -G file:當前有效用戶是否為文件屬組
雙目測試:
file1 -ef file2 file1與file2是否指向同一個設備上的相同inode file1 -nt file2 file1是否新于file2 file1 -ot file2 file1是否舊于file2
原創文章,作者:真的可行(wzb),如若轉載,請注明出處:http://www.www58058.com/33968