glob - 形成路徑名稱
很久以前 在 UNIX V6 版 中
有一個 程式
/etc/glob 用來
展開 萬用字元模板.
不久以後 它 成為 shell
內建功能. 現在 人們
開發了 類似的 庫函式
glob(3), 讓 使用者程式
實現 同樣的 功能.
此 規則 遵循 (POSIX 1003.2, 3.13).
包含 '?', '*' 或 '[' 字元的 字串
稱為 萬用字元模板(wildcard
pattern). 形成路徑名(globbing) 指
一種 操作, 把
萬用字元模板 展開為
匹配 該串的 路徑名.
匹配 定義為:
不在 方括弧中 的 '?' 匹配
任意 單個 字元.
不在 方括弧中 的 '*' 匹配
任意 字串, 包括 空串.
對於 表示式 `[...]', 如果 在
第一個 '['符 後面 出現的
第一個 字元 不是 '!', 則
該 表示式 匹配 任意
一個 在 `[...]'內 出現的
字元. 方括弧內 不能 有
空串, 因此 ']' 可以 作為
第一個 字元 出現在
方括弧內. (像 這樣, '[][!]'
匹配 下列 三個 字元
中的 任意 一個, '[', ']' 和 '!'.)
字符集 有一個 特例: 用 '-'
分開的 兩個 字元 表示
一個 範圍集. (像 這樣,
`[A-Fa-f0-9]' 等於 `[ABCDEFabcdef0123456789]'.) 把 '-'
放到 方括弧內 的 開頭
或 最後 可以 獲得 它的
本意. (像 這樣, `[]-]' 匹配
']'和'-' 中 任意 一個. 而 `[--/]'
匹配 `-', `.' 和`/'中 任意
一個.)
表示式 '[!...]' 表示 一個
字元, 該 字元 不匹配
方括弧內 去掉 開頭 '!'
後 的 表示式. (像 這樣,
`[!]a-]' 匹配 除了 ']', 'a' 和 '-' 的
任意 一個 字元.)
要 去掉 '?', '*' 和 '[' 的 特殊
含義, 可以 透過 前面 加
一個 反斜槓; 或者 在 shell
命令列 中, 透過 引號 來
引用 這些 字元. 在
方括弧內 這些 字元
顯露出 本意, 所以, '[[?*\]'
匹配 這 四個字元 中 的
一個: '[', '?', '*', '\'.
形成路徑名 功能
應用於 路徑 中 的
每一個 成員部分. 路徑
中 的 '/' 不能 被
萬用字元 '?' 或 '*', 或
範圍集 如 '[.-0]' 匹配.
範圍集 不能 直接 包含
'/', 否則 導致 語法錯誤.
如果 待匹配的 檔名
以'.'開頭, 那麼 這個 '.'
字元 必須 直接 給出.
(比如說, ´rm *' 不會 刪除
'.profile' 檔案, 'tar c *' 不會 打包
你的 所有 檔案; 用 'tar c .'
會 更好.)
上述的 簡單優雅 規則,
把 萬用字元模板
展開為 匹配的 路徑名,
來源於 最初的 UNIX 定義.
它 允許 展開出 空串,
例如
xv -wait 0 *.gif *.jpg
這裡 可能 沒有 *.gif 檔案
(而且 不算 錯誤).
然而, POSIX 要求 句法 錯誤
或 路徑名 列表 為 空 時,
保留 萬用字元模板
不變. (譯註: 即 不展開.)
在
bash 中 可以 透過 設定
allow_null_glob_expansion=true 把 它
強置為 傳統的 風格.
(其他 地方 也有 類似的
問題, 例如, 老式的 語句
是
rm `find . -name "*~"`
新的 寫法 為
rm -f nosuchfile `find . -name "*~"`
以 避免 由於
空引數呼叫
rm 而 產生
錯誤資訊.)
注意, 萬用字元模板
不是 正規表示式, 儘管
它們 有點象. 首先, 它
匹配 檔名, 而 不是 正文;
其次, 規則 不一樣, 例如
正規表示式 裡 的 '*'
代表 零個或多個
前面內容的 重複.
正規表示式 的
方括弧表示式 用 '^' 引導
取反操作, (而不是 '[!...]'). POSIX
宣告, 在 萬用字元模板
中, '[^...]' 未做 定義.
當然, 範圍集 最初 指
ASCII的 範圍, 因此 '[ -%]'
意思是 '[ !"#$%]','[a-z]'
指所有小寫字元.
一些 UNIX實現 把 這個
歸納為: 範圍 X-Y 指
X的編碼 到 Y的編碼
之間的 編碼字元. 可是,
這 要求 使用者 知道
他們 本地系統的
字元編碼, 此外, 如果
本地的 字母表順序 和
字符集順序 不對應, 那
就 更不方便了.
因此, POSIX 對
萬用字元模板 和
正規表示式 的
方括弧表達法 作了
重大擴充套件, 上面
我們 知道了
方括弧表示式 中 的
三個 型別, 它們是 (i)
取補集 (ii) 直接列出的
單個字元 和 (iii) 範圍集.
POSIX 對 範圍集 在 國際化
方面 作了 更有力的
說明, 並且 增加了 三個
型別:
(iii) 範圍 X-Y 由 X 和 Y 之間
所有的字元 組成
(包括X和Y), X 和 Y 的
當前編碼序列 由
當前場合的 LC_COLLATE
分類定義.
(iv) 命名字符集, 象
[:alnum:] [:alpha:] [:blank:] [:cntrl:]
[:digit:] [:graph:] [:lower:] [:print:]
[:punct:] [:space:] [:upper:] [:xdigit:]
因此 可以 用 '[[:lower:]]' 代替
'[a-z]', 它 在 丹麥語 裡 同樣
有效, 雖然 丹麥的
字母表 裡 'z' 後面 還有
三個 字母. 這些 字符集
由 當前場合的 LC_CTYPE
分類定義.
(v) 符號對映, 象 '[.ch.]' 或 '[.a-acute.]',
在 '[.' 和 '.]' 之間的 字串 是
定義 在 當前場合的
對映元素. 注意 這 可以
是 多字元元素.
(vi) 等類表示式, 象 '[=a=]', 在 '[='
和 '=]' 之間的 字串 是
任意 等類 中 的
對映元素, 它 定義在
當前場合. 例如, '[[=a=]]' 可以
等同於 `[a徉溻]' (警告:
這裡 有 Latin-1 字元), 也就是
`[a[.a-acute.][.a-grave.][.a-umlaut.][.a-circumflex.]]'.
sh(1),
glob(3),
fnmatch(3),
locale(7),
regex(7)
徐明 <[email protected]>
2000/10/15 第一版
2001/11/17 第一次修訂
http://cmpp.linuxforum.net
本頁面中文版由中文 man
手冊頁計劃提供。
中文 man 手冊頁計劃:
https://github.com/man-pages-zh/manpages-zh