今天看有人總結了 shell 下的參數擴展,但不是很全,剛好之前整理過放在百度空間,但百度空間目前半死不活的狀況下對 Google 很是不友好,索性一併轉過來方便查閱。php
假設咱們定義了一個變量爲:html
file=/dir1/dir2/dir3/my.file.txt
${file#*/}:拿掉第一條 / 及其左邊的字符串:dir1/dir2/dir3/my.file.txt ${file##*/}:拿掉最後一條 / 及其左邊的字符串:my.file.txt ${file#*.}:拿掉第一個 . 及其左邊的字符串:file.txt ${file##*.}:拿掉最後一個 . 及其左邊的字符串:txt ${file%/*}:拿掉最後條 / 及其右邊的字符串:/dir1/dir2/dir3 ${file%%/*}:拿掉第一條 / 及其右邊的字符串:(空值) ${file%.*}:拿掉最後一個 . 及其右邊的字符串:/dir1/dir2/dir3/my.file ${file%%.*}:拿掉第一個 . 及其右邊的字符串:/dir1/dir2/dir3/my
Tips:shell
記憶的方法爲:
# 是去掉左邊(在鍵盤上 # 在 $ 之左邊)
% 是去掉右邊(在鍵盤上 % 在 $ 之右邊)
單一符號是最小匹配﹔兩個符號是最大匹配(相似貪婪匹配)。編程
${file:0:5}:提取最左邊的 5 個字節:/dir1 ${file:5:5}:提取第 5 個字節右邊的連續 5 個字節:/dir2 ${#file}:計算出字符串的長度,/dir1/dir2/dir3/my.file.txt 字符串長度 27 ${file: -4}:提取最後四個字符串(空格是爲了不衝突,注意不一樣於echo ${file:-4},也能夠用(-4)代替空格),相似用法(提取前四個字符) ${file:0:4}
咱們也能夠對變量值裏的字符串做替換:segmentfault
${file/dir/path}:將第一個 dir 提換爲 path:/path1/dir2/dir3/my.file.txt ${file//dir/path}:將所有 dir 提換爲 path:/path1/path2/path3/my.file.txt
利用 ${ } 還可針對不一樣的變量狀態賦值(沒設定、空值、非空值):數組
${file-my.file.txt} :假如 $file 沒有設定,則使用 my.file.txt 做傳回值。(空值及非空值時不做處理) ${file:-my.file.txt} :假如 $file 沒有設定或爲空值,則使用 my.file.txt 做傳回值。 (非空值時不做處理) ${file+my.file.txt} :假如 $file 設爲空值或非空值,均使用 my.file.txt 做傳回值。(沒設定時不做處理) ${file:+my.file.txt} :若 $file 爲非空值,則使用 my.file.txt 做傳回值。 (沒設定及空值時不做處理) ${file=my.file.txt} :若 $file 沒設定,則使用 my.file.txt 做傳回值,同時將 $file 賦值爲 my.file.txt 。 (空值及非空值時不做處理) ${file:=my.file.txt} :若 $file 沒設定或爲空值,則使用 my.file.txt 做傳回值,同時將 $file 賦值爲 my.file.txt 。 (非空值時不做處理) ${file?my.file.txt} :若 $file 沒設定,則將 my.file.txt 輸出至 STDERR。 (空值及非空值時不做處理) ${file:?my.file.txt} :若 $file 沒設定或爲空值,則將 my.file.txt 輸出至 STDERR。 (非空值時不做處理)
Tips:
以上的理解在於, 你必定要分清楚 unset 與 null 及 non-null 這三種賦值狀態.
通常而言, : 與 null 有關, 若不帶 : 的話, null 不受影響, 若帶 : 則連 null 也受影響。
而 - 和 = 的區別在因而否把傳回值賦給引用變量,例如:bash
${parameter:-word} word is only substituted. ${parameter:=word} word is substituted and assigned to parameter. root@localhost ~ $ echo "$var" root@localhost ~ $ echo "${var:-hello}" hello root@localhost ~ $ echo "$var" root@localhost ~ $ echo "${var:=hello}" hello root@localhost ~ $ echo "$var" hello
Bash4中可使用兩種容器。
一種是數組,另外一種是關聯數組,相似於其餘語言中的Map/Hash/Dict。
聲明數組的經常使用語法: declare -a ARY或者ARY=(1 2 3)
聲明關聯數組的惟一語法: declare -A MAP(bash4如下不支持)
賦值的語法:
直接ARY[N]=VALUE,N能夠是數字索引也能夠是鍵。關聯數組可使用MAP=([x]=a [y]=b)進行多項賦值,注意這是賦值的語句而不是聲明。
親測數組中的索引不必定要按順序來,你能夠先給2和3上的元素賦值。(一樣算是弱類型的Javascript也支持這種無厘頭賦值,這算通病麼?)函數
往現有數組批量添加元素: ARY+=(a b c) MAP+=([a]=1 [b]=2) 取值: ${ARY[INDEX]} ${MAP[KEY]} 注意花括號的使用 ${A[@]} 展開成全部的變量,而獲取數組長度使用 ${#A[@]} 切片: ${ARY[@]:N:M} N是offset而M是length 返回索引,至關於keys(): ${!MAP[@]} 試試下面的代碼: declare -a ARY declare -A MAP MAP+=([a]=1 [b]=2) ARY+=(a b c) echo ${ARY[1]} echo ${MAP[a]} echo "${ARY[@]}" echo "${MAP[@]}" echo "${ARY[@]:0:1}" echo ${#ARY[@]} echo "${!MAP[@]}" ARY[4]=a echo ${ARY[@]} echo ${ARY[3]}
HI=HellO echo "$HI" # HellO echo ${HI^} # HellO echo ${HI^^} # HELLO echo ${HI,} # hellO echo ${HI,,} # hello echo ${HI~} # hellO echo ${HI~~} #hELLo ^大寫,,小寫, ~大小寫切換 重複一次只修改首字母,重複兩次則應用於全部字母。 混着用會怎樣? echo ${HI^,^} # HellO 看來是不行的×_×
上面應該見識到了 shell 中大括號的強大功能,其實 shell 下有不少種括號,不像其它高級語言括號只起到語法和意義的做用,而 shell 下的每種括號除了語法、語義的做用以外,還對 shell 編程起到了功能上的擴展。spa
2.1 () 在子shell中運行 (a=1);echo $a,結果是空,由於a=1不是在當前shell中運行的(a=1);(echo $a)也是空的。 小技巧:(cd $path, do something) 可讓不切換當前目錄而在其它目錄乾點別的事兒~ () 還有個功能是數組的賦值:好比a=(1 3 5),那麼${a[0]}=1;${a[1]}=3;${a[2]}=5,須要注意的是,下標是從0開始的。 2.2 (()) 表達式計算 a=1;((a++));echo $a,這時a就是2了。 2.3 <() 和 >() 進程代入,能夠把命令的執行結果當成文件同樣讀入 好比comm前通常須要sort,那就能夠這樣comm <(sort 1.lst) <(sort 2.lst) 或者是paste <(cut -t2 file1) <(cut -t1 file1),和管道差很少,可是支持多個輸入。 2.4 $() $(cmd) 執行cmd的結果, 好比cmd是echo ls,那麼就是執行ls,好比file $(which bash),which bash的結果是/bin/bash, 因此file $(which bash)等於file /bin/bash。若是你$(ls),並且你的當前目錄下只有a b兩個文件, 那麼就是執行a b,而後系統會提示,命令沒找到。$() 基本和 `` 等價。 2.5 $(()) 表達式擴展, 和(())很類似,可是這個是有點不一樣,$(())不能直接$((b++)),例如:b=1;echo $((++b)) 這時b等於2,顯示的也是2,b=1; echo $((b++))這時b等於2,顯示的是1. 2.6 [] 和 [[]],[] 就是 test,[]和[[]]都是條件表達式,不過[[]]有比[]高的容錯性, 若是a爲空,那麼[ $a -eq 0 ]會報錯,可是[[ $a -eq 0 ]]不會,因此通常都會使用[[]]或者是 [ "$a" -eq 0 ],[[]]支持的功能也比 [] 多,好比[[ aaa =~ a{3} ]],[] 還有一種用途, 若是你的當前目錄下有a1-a9九個文件,你能夠用a[1-9]來替代這九個文件。 有點須要注意,你不能用a[1-20]來代替a1- a20,必需要a[1-9] a1[0-9] a20。 可是須要注意的是 [[]] 數字進制轉換的坑~ 2.7 $[] 是 $(()) 的過去形式,如今已經不建議使用。 2.8 {n..m} {1..30} 就是1-30,或者是/{,s}bin/表示/bin/和/sbin/,ab{c,d,e}表示abc、abd、abe, 小技巧:文件備份:cp a.sh{,.bak} 而 { cmd1; cmd2; } 的做用是定義一個命令組,通常用在單行的條件表達式中: [[ 1 -eq 2 ]] && echo True || { echo False; echo "Program will exit!"; } 其實 shell 函數的語法也是它的變體: a(){ i=$1; echo $((i++)); echo $((++i)); } && a 1 2.9 ${} 變量的Parameter Expansion, 用法不少,最基本的 ${var}1,防止變量擴展衝突,具體能夠查看man bash。 或者參考我以前的博文連接:http://hi.baidu.com/leejun_2005/blog/item/ebfee11a4177ddc1ac6e751d.html
三、bash命令執行流程:.net
執行分爲四大步驟:輸入、解析、擴展和執行。
四、Refer:
[1] shell十三問之大括號參數擴展(Parameter Expansion)
http://hi.baidu.com/leejun_2005/item/138c09343aaddff6e6bb7a49
[2] shell 十三問?
http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=218853&page=7#
[3] shell/bash編程中各種括號的應用
http://hi.baidu.com/leejun_2005/item/6f9eb7345e5f4f302f20c453
[4] Bash Hackers Wiki Frontpage » Syntax » Parameter expansion
http://wiki.bash-hackers.org/syntax/pe
[5] 玩轉Bash變量
http://segmentfault.com/blog/spacewander/1190000002539169
[6] Bash快速入門指南
http://blog.jobbole.com/85183/
[7] SHELL(bash)腳本編程六:執行流程