bash 教程 shell 模式擴充套件 [MD]
我的GitHub | 我的部落格 | 我的微信 | 我的郵箱 |
---|---|---|---|
baiqiantao | baiqiantao | bqt20094 | [email protected] |
目錄
目錄Bash 的模式擴充套件
本文改編自 網道的 Bash 教程,主要為了精簡大量本人不感興趣的內容。
簡介
Shell 接收到使用者輸入的命令以後,會根據空格將使用者的輸入,拆分成一個個詞元(token
)。然後,Shell 會擴充套件詞元裡面的特殊字元(~
、?
、*
、[]
、{}
、$
),擴充套件完成後才會呼叫相應的命令。這種特殊字元的擴充套件,稱為模式擴充套件(globbing
)。
Bash 是先進行擴充套件,再執行命令。擴充套件的結果是由 Bash 負責的,與所要執行的命令無關。命令本身並不存在引數擴充套件,收到什麼引數就原樣執行。
模組擴充套件的英文單詞是
globbing
,這個詞來自於早期的 Unix 系統有一個/etc/glob
檔案,儲存擴充套件的模板。後來 Bash 內建了這個功能,但是這個名字就保留了下來。
模式擴充套件與正則表示式的關係是:模式擴充套件的出現早於正則表示式,可以看作是原始的、早期的、低配版正則表示式,它的功能沒有正則那麼強大靈活,但是優點是簡單和方便。
set -f # 【set -o noglob】關閉擴充套件
set +f # 【set +o noglob】開啟擴充套件
檔名擴充套件
檔名擴充套件字元只有 檔案存在 的前提下才會擴充套件,如果不存在可匹配的檔名,就會原樣輸出。
使用者主目錄 ~
波浪線~
會擴充套件成當前使用者的主目錄。
echo ~ # 【/home/bqt】波浪線 ~ 會擴充套件成當前使用者的主目錄 echo ~/foo # 【/home/bqt/foo】主目錄的某個子目錄 echo ~root # 【/root】使用者 root 的主目錄 echo ~foo # 【~foo】如果使用者名稱 foo 不存在,就會原樣輸出 echo ~+ # 擴充套件成當前所在的目錄,等同於【pwd】命令
單個字元 ?
字元?
代表檔案路徑裡面的任意單個字元,不包括空字元。
ls ?.txt # 【a.txt】字元 ? 代表檔案路徑裡面的任意單個字元,不包括空字元
ls ??.txt # 【ab.txt】如果匹配多個字元,就需要多個 ? 連用
echo ?.bqt # 【?.bqt】如果不存在可匹配的檔名,就會原樣輸出
任意字元 *
字元*
代表檔案路徑裡面的任意數量的任意字元,包括零個字元。*
不會匹配以.
開頭的隱藏檔案
echo *.txt # 【a.txt ab.txt】字元 * 代表檔案路徑裡面的任意數量的任意字元,包括零個字元
echo * # 輸出當前目錄所有檔案,不包括以 . 開頭的隱藏檔案,不包括子目錄中的檔案
echo *.bqt # 【*.bqt】如果不存在可匹配的檔名,就會原樣輸出
echo .* # 輸出當前目錄所有隱藏檔案(即以 . 開頭的檔案)
echo .[!.]* # 輸出當前目錄所有隱藏檔案,同時排除 .(當前目錄)和 ..(上級目錄)這兩個隱藏檔案
*
只匹配當前目錄,不會匹配子目錄
echo */ # 輸出當前目錄所有子目錄
echo */* # 輸出當前目錄所有子目錄中的所有檔案
echo */*/ # 輸出當前目錄所有二級子目錄
echo */*/* # 輸出當前目錄所有二級子目錄中的所有檔案,有幾層子目錄,就必須寫幾層星號
開啟 globstar
引數以後,**
可以匹配零個或多個任意深度子目錄(Bash 4.0 中新增)
shopt globstar # 查詢某個引數關閉還是開啟,globstar 引數預設是關閉的
shopt -s globstar # 開啟某個引數,開啟 globstar 引數以後,** 可以匹配零個或多個子目錄
shopt -u globstar # 關閉某個引數
echo **/* # 輸出當前目錄以及【任意深度子目錄】中的所有檔案
任一字元 []
- 方括號擴充套件
[...]
可以擴充套件任意一個括號之中的字元 - 排除模式
[^...]
和[!...]
可以擴充套件任意一個不在方括號中的字元 - 如果需要匹配字元
[
,可以放在方括號內任意位置,不支援匹配字元]
- 如果需要匹配字元
-
,只能放在方括號內部的開頭或結尾
echo [ab].txt # 方括號擴充套件 [...] 可以擴充套件任意一個括號之中的字元
echo [^ab] # 等價於 [!ab],表示擴充套件任意一個不在方括號中的字元
echo [[ab] # 如果需要匹配字元 [,可以放在方括號內任意位置,不支援匹配字元 ]
echo [-ab] # 如果需要匹配字元 -,只能放在方括號內部的開頭或結尾
echo [ab].bqt # 【[ab].bqt】如果不存在可匹配的檔名,就會原樣輸出
方括號擴充套件有一個簡寫形式[start-end]
,表示匹配一個連續的範圍。
[a-z]
:所有小寫字母的字元[!a-z]
:所有非小寫字母的字元[a-zA-Z]
:所有小寫字母 + 大寫字母[a-zA-Z0-9]
:所有小寫字母 + 大寫字母 + 數字program.[co]
:檔案program.c
與檔案program.o
BACKUP.[0-9][0-9][0-9]
:所有以BACKUP.
開頭,後面是三個數字的檔名
字元類 [[:class:]]
[[:class:]]
表示一個字元類,擴充套件成某一類特定字元之中的一個。
[[:digit:]]
:匹配任意數字 0-9[[:lower:]]
:匹配任意小寫字母 a-z[[:upper:]]
:匹配任意大寫字母 A-Z[[:alpha:]]
:匹配任意英文字母[[:alnum:]]
:匹配任意英文字母與數字[[:cntrl:]]
:ASCII 碼 0-31 的不可列印字元[[:print:]]
:ASCII 碼 32-127 的可列印字元[[:punct:]]
:標點符號(除了 A-Z、a-z、0-9 的可列印字元)[[:graph:]]
:匹配任意英文字母、數字、標點符號[[:blank:]]
:空格和 Tab 鍵[[:space:]]
:空格、Tab、LF(10)、VT(11)、FF(12)、CR(13)[[:xdigit:]]
:匹配16進位制字元(A-F、a-f、0-9)
echo [[:upper:]]* # 輸出所有以大寫字母開頭的檔名
echo [![:digit:]]* # 輸出所有不以數字開頭的檔名
echo [[:blank:]]* # 【[[:blank:]]*】如果不存在可匹配的檔名,就會原樣輸出
量詞語法 ?+*!@()
量詞語法用來控制模式匹配的次數。它只有在 Bash 的 extglob
引數開啟的情況下才能使用,不過一般是預設開啟的。
shopt extglob # 查詢某個引數關閉還是開啟,extglob 引數預設是開啟的
shopt -s extglob # 開啟某個引數,開啟 extglob 引數以後,可以使用量詞語法
shopt -u extglob # 關閉某個引數
?(pattern-list)
:匹配零個或一個模式*(pattern-list)
:匹配零個或多個模式+(pattern-list)
:匹配一個或多個模式@(pattern-list)
:只匹配一個模式!(pattern-list)
:匹配給定模式以外的任何內容
ls abc?(def) # 【abc abcdef】匹配以 abc 開頭、且以零個或一個 def 結尾的檔案
ls abc+(.txt|.php) # 【abc.php abc.txt】匹配以 abc 開頭、且以 .txt 或 .php 結尾的檔案
ls abc+(.txt) # 【abc.txt abc.txt.txt】匹配以 abc 開頭、且以 .txt 結尾的檔案
ls a!(b)c.txt # 【aac.txt ac.txt】匹配除了 abc.txt 以外,以 a 開頭、且以 c.txt 結尾的檔案
echo abc*(.bqt) # 【abc*(.bqt)】如果不存在可匹配的檔名,就會原樣輸出
字串擴充套件
所有值 {}
大括號擴充套件 {...}
表示分別擴充套件成大括號裡面的所有值。
- 各個值之間使用逗號分隔,值可以是多字元的模式
- 逗號前面可以沒有值,表示擴充套件的第一項為空
- 逗號前後不能有空格,否則,Bash 會認為這不是大括號擴充套件,而是獨立的引數
- 大括號可以巢狀,可以與其他模式聯用,並且總是先於其他模式進行擴充套件
- 大括號擴充套件不是檔名擴充套件,它總是會擴充套件的,這與方括號擴充套件
[...]
完全不同
echo {1,2,3} # 【1 2 3】大括號擴充套件 {...} 表示分別擴充套件成大括號裡面的所有值
ls {,a,abc}.txt # 依次訪問 .txt a.txt abc.txt 三個檔案,而不管檔案是否存在
echo a{a{1,2},b{3,4}} # 【aa1 aa2 ab3 ab4】支援巢狀
echo /bin/{cat,ba*} # 大括號也可以與其他模式聯用,並且總是先於其他模式進行擴充套件
大括號擴充套件可直接用於for
迴圈。
for i in {1,2,4,白乾濤}
do
echo $i
done
- 大括號擴充套件的簡寫形式
{start..end}
表示擴充套件成一個連續序列 - 大括號擴充套件另一個簡寫形式
start..end..step
可指定擴充套件的步長 - 簡寫形式支援逆序、支援巢狀
echo {01..5} # 【01 02 03 04 05】擴充套件成一個連續序列
echo {0..8..2} # 【0 2 4 6 8】可指定擴充套件的步長
echo {a..c}{1,2} # 【a1 a2 b1 b2 c1 c2】多個簡寫形式連用,會有迴圈處理的效果
echo .{mp{5..3},mkv} # 【.mp5 .mp4 .mp3 .mkv】支援逆序,支援巢狀
echo {a1..3c} # 【{a1..3c}】遇到無法理解的簡寫時會原樣輸出,不會擴充套件
美元符號擴充套件
變數擴充套件 $
Bash 將美元符號$
開頭的詞元視為變數,將其擴充套件成變數值。${!string*}
或${!string@}
返回所有匹配給定字串string
的變數名。
echo $SHELL # 【/bin/bash】
echo ${SHELL} # 【/bin/bash】變數名也可以放在 ${} 裡面
echo ${!S*} # 返回所有以 S 開頭的變數名,如果不存在,則返回空
子命令擴充套件 $(...)
$(...)
可以擴充套件成另一個命令的執行結果,該命令的所有輸出都會作為返回值。
echo $(date) # 返回 date 命令的執行結果,注意 date 是一個命令而非一個變數
echo `date` # 將子命令放在反引號之中,也可以擴充套件成命令的執行結果
echo $(ls $(pwd)) # 子命令擴充套件可以巢狀
算術擴充套件 $((...))
$((...))
可以擴充套件成整數運算的結果。
echo $((2 + 2)) # 4
模式擴充套件相關的 shopt 命令
shopt
命令可以調整 Bash 的行為。它有好幾個引數跟萬用字元擴充套件有關。
shopt [optionname] # 查詢某個引數關閉還是開啟
shopt -s [optionname] # 開啟某個引數
shopt -u [optionname] # 關閉某個引數
- dotglob:預設關閉,可以讓擴充套件結果包括隱藏檔案,即以點開頭的檔案。
- nullglob:預設關閉,可以讓萬用字元不匹配任何檔名時,返回空字串而非
原樣返回
。 - failglob:預設關閉,可以讓萬用字元不匹配任何檔名時,直接報錯,而非繼續讓各個命令去處理。
- extglob:預設開啟,可以讓 Bash 支援 ksh 的一些擴充套件語法。它的主要應用是支援
量詞語法
。 - nocaseglob:預設關閉,可以讓萬用字元擴充套件不區分大小寫。
- globstar:預設關閉,可以讓
**
匹配零個或多個子目錄(Bash 4.0 中新增)。
模式擴充套件使用注意點
- 萬用字元是先解釋,再執行:Bash 接收到命令以後,如果發現裡面有萬用字元,會先進行萬用字元擴充套件,然後再執行命令。
- 檔名擴充套件在沒有可匹配的檔案時,會原樣輸出。
- 所有檔名擴充套件只匹配單層路徑,無法匹配子目錄裡面的檔案(即:不能匹配路徑分隔符
/
)。 - Bash 允許檔名使用萬用字元,即檔名包括特殊字元。這時引用檔名,需要把檔名放在
單引號或雙引號
裡面。
2022-1-2
本文來自部落格園,作者:白乾濤,轉載請註明原文連結:https://www.cnblogs.com/baiqiantao/p/15758543.html