1. 程式人生 > >正則表示式和萬用字元概念的區別

正則表示式和萬用字元概念的區別

首先,shell萬用字元和正則表示式是風馬牛不相及的東西。請首先樹立這個概念。

    萬用字元,說白了一般只用於檔名匹配,它是由shell解析的。所謂的系統level的概念非常含糊,什麼是系統level的?我們知道shell是一個命令直譯器,它是核心的外殼,用於完成作業系統使用者與核心的溝通,因此,萬用字元實際上就是一個shell直譯器去解析的符號,它的特殊涵義是由shell這個命令直譯器賦予的。萬用字元的英文名是wildcard,就是萬用牌的意思,它相當簡單,一般來說,*nix系統上面的shell大多將三個特殊符號當作萬用字元,它們是 * ? [...],其中 * 表示匹配任意長度的任意字元; ? 表示匹配一個任意字元,而[...]則表示匹配括號中列出的字元中的任意一個。

    其次。什麼是正則表示式(regularexpression, 縮寫是regex.)?從簡單的角度去理解,你可以把正則表示式看成是一種字串匹配模式標準。這裡最重要的就是,它本身,只是一種業界流行的標準,或者說,它是相當於對字串匹配模式的一種規定。這種規定是隨著相關的工具軟體的發展而自稱體系的“不成文規矩”。

   -- 舉個例子好了。假設首先有一種工具軟體能夠根據“模式(pattern)”搜尋字串,這個工具非常流行,以至於後續的工具軟體都效仿那個工具軟體定義的模式規則來匹配字串 -- 慢慢的就形成標準,而且相對來說是一種不成文的規矩.

    所以,正則表示式是什麼?-- 它是一種對字串匹配模式的描述和規定 -- 並且是一種標準。而不同的工具程式,也就是egrep、sed、awk這樣的程式,以各種程度來支援這種字串搜尋模式,它們就是標準的實現,你可以在這種軟體中使用正則表示式這種“匹配模式標準”。 -- 明白?

    所以,在什麼地方使用萬用字元?答案是隻要是shell命令列或者shell指令碼中,你都可以使用萬用字元;

    在什麼地方使用正則表示式?當你使用能夠支援正則表示式的工具軟體進行字串處理時你就可以使用正則表示式。你還可以在支援正則表示式的語言中使用正則表示式,比如perl, java... C++中也有專門用於支援正則表示式的庫。正則表示式總是和“使用什麼工具軟體或者語言”相關。相對來說,不同的工具和語言對正則表示式的支援程度不同,*nix裡面將這些工具軟體的對正則表示式的支援分類,因此也就有了“基礎正則表示式”和“擴充套件正則表示式”。

    不同的工具對正則表示式的支援,其實有些許的微妙不同;但是總體來說,使用正則還是基本按照標準來的。這些不同的工具支援程度,被稱之為“正則流派”。而工具軟體中支援這種匹配模式的那部分程式碼,稱之為“正則引擎”。由於perl對正則表示式的支援非常到位,其正則引擎也比較優秀,因此perl語言算是正則的一大流派,目前大部分對正則的支援都或多或少參考了perl語言中的標準。

    嗯。現在你應該明白了,我說shell萬用字元的*和正則表示式的*為什麼是兩回事。因為shell萬用字元和正則表示式根本就是兩回事。

    實際上,它們的涵義也不一樣。shell萬用字元表示“去匹配0到任意個任意字元”,比如 *.c 表示匹配 xxx.c yyy.c zzz.c ...

    而在正則表示式中,"*"表示,“去匹配重複0到任意個*前的那個字元”。比如, oo* 表示匹配 o, oo, ooo, oooo...

LZ,給點鼓勵,我打了好多字~看來我十分好為人師... 見笑了。我也是粗通此理,見LZ正好疑惑,所以不禁胡言亂語了一通。若我有誤則請多多包涵... 吾生也有涯,而知也無涯,以有涯隨無涯,殆矣... 我自然也有各種要請教的...

比如查詢當前目錄下的字尾為.c的檔案。你可以使用 
   $ find . -name *.c
   在這個命令中, 首先shell讀入整個命令列,然後對這個命令列進行解析。當然, “*.c” 也由shell解析了。


   你還可以使用一個命令:
   $find . -name "*"  | grep '[.]c$'
   在這個命令中,首先shell讀入整個命令列,然後對整個命令列進行解析。注意,find . -name "*",這裡的"*"是由shell解析的,它代表了任意檔案。

   然後,find出來的結果通過管道,由grep再進行處理。我們看到grep裡面使用了正則表示式 [.]c$, 而且這個正則表示式是用單引號包圍起來的,單引號包圍的目的就是告訴shell直譯器:你不要解析這裡面(單引號包圍的部分)的東西了,這裡面的東西應該原封不動地送給grep工具解析。

   所以,為什麼使用grep的時候,一個好的習慣是把正則表示式用單引號圍起來?原因就是避免shell先對正則表示式中的“*”進行了解析,然後再把一個不正確的正則表示式(被shell先解析並更改了的)送給grep.
   

   再次重申。雖然,萬用字元的*也可以看成是一種字串匹配模式,但是它是由shell進行解析的字串匹配模式,跟由支援正則的工具軟體解析的“正則字串匹配模式”完全不同,是風馬牛不相及的東西。(當然,非要說它們(shell和正則工具)的字元搜尋引擎實現原理可能有些關聯之類的,我無話可說)。