glob 模式匹配簡介

轉自:http://www.zybang.com/question/62a9c6f4f875fc3cab6dead25a3a7ad8.html

英文原版地址:http://www.man7.org/linux/man-pages/man7/glob.7.html

個人觀點:最近項目需要用到了模式匹配路徑下的文件名的功能,網上的資料幾乎都是一樣的,還是看man手冊裏寫的比較全面。

我使用了系統函數fnmatch,第三個參數寫得是0, 實現了* ? 【】的模式匹配, 和正則表達式還差很多, 但是這個功能也比較不錯了,

在網上找了源代碼,有兩份,一份是apple的,另一份是linux的。

apple源代碼:http://www.man7.org/linux/man-pages/man3/glob.3.html

linux源代碼詳見coreutils-8.25/lib/fnmatch.c以下粘出部分代碼:

int
fnmatch (const char *pattern, const char *string, int flags)
{
# if HANDLE_MULTIBYTE
#  define ALLOCA_LIMIT 2000
  if (__builtin_expect (MB_CUR_MAX, 1) != 1)
    {
      mbstate_t ps;
      size_t patsize;
      size_t strsize;
      size_t totsize;
      wchar_t *wpattern;
      wchar_t *wstring;
      int res;

      /* Calculate the size needed to convert the strings to
         wide characters.  */
      memset (&ps, '\0', sizeof (ps));
      patsize = mbsrtowcs (NULL, &pattern, 0, &ps) + 1;
      if (__builtin_expect (patsize != 0, 1))
        {
          assert (mbsinit (&ps));
          strsize = mbsrtowcs (NULL, &string, 0, &ps) + 1;
          if (__builtin_expect (strsize != 0, 1))
            {
              assert (mbsinit (&ps));
              totsize = patsize + strsize;
              if (__builtin_expect (! (patsize <= totsize
                                       && totsize <= SIZE_MAX / sizeof (wchar_t)),
                                    0))
                {
                  errno = ENOMEM;
                  return -1;
                }

              /* Allocate room for the wide characters.  */
              if (__builtin_expect (totsize < ALLOCA_LIMIT, 1))
                wpattern = (wchar_t *) alloca (totsize * sizeof (wchar_t));
              else
                {
                  wpattern = malloc (totsize * sizeof (wchar_t));
                  if (__builtin_expect (! wpattern, 0))
                    {
                      errno = ENOMEM;
                      return -1;
                    }
                }
              wstring = wpattern + patsize;

              /* Convert the strings into wide characters.  */
              mbsrtowcs (wpattern, &pattern, patsize, &ps);
              assert (mbsinit (&ps));
              mbsrtowcs (wstring, &string, strsize, &ps);

              res = internal_fnwmatch (wpattern, wstring, wstring + strsize - 1,
                                       flags & FNM_PERIOD, flags);

              if (__builtin_expect (! (totsize < ALLOCA_LIMIT), 0))
                free (wpattern);
              return res;
            }
        }
    }

# endif /* HANDLE_MULTIBYTE */

  return internal_fnmatch (pattern, string, string + strlen (string),
                           flags & FNM_PERIOD, flags);
}



以下是從網上轉載的,對man手冊中glob的翻譯:

GLOB

Section: \7Linux Programmer's Manual\7 (7)
Updated: 12 June
1998
Index
NAME
glob - 形成路徑名稱
描述 (DESCRIPTION)
很久以前 在 UNIX V6 版 中 有一個 程序 /etc/glob 用來 展開 通配符模板.
不久以後 它 成爲 shell 內建功能. 現在 人們 開發了 類似的 庫函數 glob(3), 讓 用戶程序 實現 同樣的 功能.
此 規則 遵循 (POSIX 1003.2, 3.13).
通配符匹配 (WILDCARD MATCHING)
包含 '?', '*' 或 '[' 字符的 字符串 稱爲 通配符模板(wildcard
pattern). 形成路徑名(globbing) 指 一種 操作, 把 通配符模板 展開爲 匹配 該串的 路徑名. 匹配 定義爲:
不在 方括弧中 的 '?' 匹配 任意 單個 字符.
不在 方括弧中 的 '*' 匹配 任意 字符串, 包括 空串.
字符集 (Character classes)
對於 表達式 `[...]', 如果 在 第一個 '['符 後面 出現的 第一個 字符 不是
'!', 則 該 表達式 匹配 任意 一個 在 `[...]'內 出現的 字符. 方括弧內 不能 有 空串, 因此 ']' 可以 作爲 第一個 字符 出現在
方括弧內. (像 這樣, '[][!]' 匹配 下列三個 字符 中的 任意 一個, '[', ']' 和 '!'.)
範圍集 (Ranges)
字符集 有一個 特例: 用 '-' 分開的 兩個 字符 表示 一個 範圍集. (像 這樣, `[A-Fa-f0-9]'
等於 `[ABCDEFabcdef0123456789]'.) 把 '-' 放到 方括弧內 的 開頭 或 最後 可以 獲得 它的 本意. (像 這樣,
`[]-]' 匹配 ']'和'-' 中 任意 一個. 而 `[--/]' 匹配 `-', `.' 和`/'中任意 一個.)
補集 (Complementation)
表達式 '[!...]' 表示 一個 字符, 該 字符 不匹配 方括弧內 去掉 開頭 '!' 後的
表達式. (像 這樣, `[!]a-]' 匹配 除了 ']', 'a' 和 '-' 的 任意 一個 字符.)
要 去掉 '?', '*' 和 '[' 的 特殊 含義, 可以 通過 前面 加 一個 反斜槓; 或者 在 shell 命令行 中, 通過 引號 來 引用
這些 字符. 在 方括弧內 這些 字符 顯露出 本意, 所以, '[[?*\]' 匹配 這 四個字符中 的 一個: '[', '?', '*', '\'.
路徑名 (PATHNAME)
形成路徑名 功能 應用於 路徑 中 的 每一個 成員部分. 路徑 中 的 '/' 不能 被通配符 '?' 或
'*', 或 範圍集 如 '[.-0]' 匹配. 範圍集 不能 直接 包含 '/', 否則 導致 語法錯誤.
如果 待匹配的 文件名 以'.'開頭, 那麼 這個 '.' 字符 必須 直接 給出. (比如說, 用 'tar c .' 會 更好.)
空列表 (EMPTY LISTS)
上述的 簡單優雅 規則, 把 通配符模板 展開爲 匹配的 路徑名, 來源於 最初的 UNIX 定義. 它
允許 展開出 空串, 例如 xv -wait 0 *.gif *.jpg
這裏 可能 沒有 *.gif 文件 (而且 不算 錯誤).
然而, POSIX 要求 句法 錯誤 或 路徑名 列表 爲 空 時, 保留 通配符模板 不變. (譯註: 即 不展開.)
在 bash 中 可以 通過 設置 allow_null_glob_expansion=true 把 它 強置爲 傳統的
風格. (其他 地方 也有 類似的 問題, 例如, 老式的 語句 是
rm `find . -name "*~"`
新的 寫法 爲
rm -f nosuchfile `find . -name "*~"`
以 避免 由於 空參數調用 rm 而 產生 錯誤信息.)
注意 (NOTES)
正規表達式 (Regular expressions)
注意, 通配符模板 不是 正規表達式, 儘管 它們 有點象. 首先, 它 匹配 文件名,
而 不是 正文; 其次, 規則 不一樣, 例如 正規表達式 裏 的 '*' 代表 零個或多個 前面內容的 重複.
正規表達式 的 方括弧表達式 用 '^' 引導 取反操作, (而不是 '[!...]'). POSIX 聲明, 在 通配符模板 中, '[^...]'
未做 定義.
字符集 和 國際化 (Character classes and Internationalization )
當然, 範圍集 最初 指
ASCII的 範圍, 因此 '[ -%]' 意思是 '[ !"#$%]',
一些 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.]]'.
SEE ALSO
sh(1), glob(3), fnmatch(3),
locale(7), regex(7)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章