${var:-word} 如果var存在且非空,則返回var,否則返回word但是不替換var
${var:+word} 如果var存在且非空,則返回word(不替換var),否則返回var
${var:=word} 如果var存在或爲空,則返回var,否則返回word且替換var
${var:?message} 如果var存在且非空,返回var,否則返回"var:message"這個字符串
${var:offset} 在var中提從offset到其末尾的子字符串
${var:offset:length} 在var中從offset開始提取length長的子字符串
${var#pattern} 返回刪除掉var中開頭pattern最短匹配後剩餘的字符串
${var##pattern} 返回刪除掉var中開頭pattern最長匹配後剩餘的字符串
${var%pattern} 返回刪除掉var中結尾pattern最短匹配後剩餘的字符串
${var%%pattern} 返回刪除掉var中結尾pattern最長匹配後剩餘的字符串
${var/pattern/string} 用string替換var中開頭pattern的最短匹配
${var//pattern/string} 用string替換var中開頭pattern的最長匹配
例子:
${*:-.} 如果沒有提供位置參數則使用當前目錄
${path##*/} 從全路徑中獲取基本文件名,等價於basename(外部程序沒shell內置機制效率高)
${path%/*} 獲取目錄名,等價於dirname(外部程序沒shell內置機制效率高)
2.命令替換及應用
$(command)
`command`
ROOT=`pwd` <=> ROOT=$(pwd)
3.數學運算
let i=i+1 bash 內置變量(不能加空格)
((i += 2)) 運算符可用空格隔開
i=`expr 3 \* 5` 注意需要轉義符
i=$(expr 3 \* 5)
i=`echo "scale=2; $TSIZE/$SSIZE*100" | bc -l` bc命令不一定每個linux用戶都安裝了
declare -i a=1 b=2;declare c=a+b 聲明稱整數來計算
4.數組及應用
數組初始化:
var[index]=value 整數做下標
var[string]=value 字符串做下標
var=(value1 value2 ...) 空格隔開
清空數組:
var=
unset var
unset var[value]
引用數組數據:
${var} 引用不帶下標的數組,得到數組第一個元素
${var[variable]} 下標使用變量時不需要美元符號引用
${var[@]} 得到數組所有元素
${var[*]} 得到數組所有元素
${#var[@]} 得到數組元素個數
${#var[*]} 得到數組元素個數
5.特殊變量
$$ 當前shell的PID
$! 在後臺運行的最後一個作業的PID
$? 關於上個執行指令的回傳碼
$0 當前shell的名字
$n (n:1-) 位置參數
$# 參數個數
$* 所有位置參數組成的單一字符串
$@ 每個位置參數的字符串組合成的
$*和$@的區別
$*將所有位置參數作爲單一字符串
$@是所有位置參數的字符串組合
function "$*" 函數參數只有一個
function "$@" 函數參數有多個
6.命令行選項
通常使用getopts,第一個冒號表示用戶鍵入錯誤選項時不提示
$OPTARG表示選項對應的參數值,$OPTIND表示命令行選項的索引
模板:
while getopts ":X1:X2:..." opt;do
case $opt in
x1) value_x1=$OPTARG;;
X2) ..;;
esac
done
shift $(($OPTIND-1))
7.命令行解析
一個shell命令行的完整處理過程:
1).將輸入分隔成記號(記號包括單詞,關鍵字,I/O定向符,分號等)
2).檢測每個命令的第一個記號,若爲開發關鍵字(像if等)則繼續匹配一個完整的符合命令,重複處理完成,返回步驟1。
3).別名檢測(檢測第一個記號是別名就進行替換,返回步驟1)
4).大括號擴展(a{b,c}擴展爲ab ac)
5).~符號擴展(如果存在替換爲$HOME)
6).變量(參數)替換(以$開頭的表達式)
7).命令替換(對$(string)形式進行)
8).算術替換(對$((string))進行計算)
9).單詞分隔(使用$IFS中的字符分隔參數,命令,算術替換中的部分成單詞)
10).路徑名擴展(通配符擴展,例如*,/等)
11).命令查詢(函數>內置命令>腳本和可執行程序)
12).運行命令(設置完I/O重定向後執行命令)
單引號‘’(繞過前10個步驟)
單引號中的命令只能執行路徑擴展,命令查找
雙引號""(繞過步驟1~5,9,10)
雙引號中可以使用參數替換,命令替換,算術替換
命令查找順序可以用command,builtin,enable來修改
command刪除別名和函數查找
builtin只查找內置命令
enable -a顯示所有命令及其是否可用
eval通知shell接受eval參數,並再次通過命令行處理的所有步驟來運行
所以被繞過的步驟可以重新解析
shell解析命令順序
別名>關鍵字>函數>內置命令>腳本和可執行程序
8.進程控制
作業編號指當前運行在用戶shell下的後臺進程(不同shell窗口下的作業毫無關係)
進程ID指當前運行在整個系統上的所有用戶的進程
作業控制:
jobs -l列出作業的完整信息
引用後臺作業的方式:
fg %N 作業編號N
fg %string 作業命令名以string開始的作業
fg %?string 作業命令包含的string的作業
fg %+ 最近被調用的後臺作業(引用被放到後臺的最新作業)
fg %% 同上
fg %- 第二個最近被調用的後臺作業
fg (不帶%) 作業進程ID
使用的作業控制的好處:
有可能前臺的作業運行時間很長,而你還想用控制終端做其他操作,這是就可以將其放到後臺
CTRL-Z即將當前作業放到後臺
kill用法:
kill參數可以使進程ID,作業編號,進程命令名
kill默認發送TERM信號到目標,但可以改變所發信號類型
kill -l 列出支持的所有信號名稱和編號列表
CTRL-C INIT
CTRL-\ QUIT
CTRL-Z TSTP
kill TERM
stty signame char可以綁定信號到什麼控制鍵上 例如:stty intr ^X
kill %作業編號
kill 進程ID
kill 進程名
kill 信號類型 參數
協同程序:
shell命令行下協同,執行命令之間使用&即可
腳本里面,最後必須加上wait命令保證所有後臺作業都完成
模式:
命令1 &
...
命令2
wait
進程使用系統資源的特性:CPU密集型,I/O密集型,交互式
對於I/O密集型使用一個大型計算的作用會較好
對於CPU密集型,多通過shell併發執行回提高效率
當在一個多CPU計算機上啓動一個後臺作業時,計算機會將其賦予到下一個可用處理器
這意味着兩個作業時間上運行在同一時刻,所有能提升效率
子shell:
子shell繼承的東西:
1)當前目錄
2)環境變量
3)標準輸入,標準輸出,標準錯誤,以及其他任何打開的文件描述符
4)被忽略的信號(trap)
未繼承的東東:
1)shell變量(除了環境變量和定義在環境文件中.bashrc的變量)
2)沒被忽略的信號處理
exec精髓,替換本shell來執行exec參數中的命令對本shell一直髮生影響
exec 2>errlog 把腳本中所有錯誤寫到errlog文件中(放在腳本開頭)
exec switch_root /newroot "/sbin/init" 啓動腳本中常常見到