在認識了 char. set 這個概念後, 然後再讓我們多認識幾個 RE 中常見的 meta 字符:
- 錨點(anchor)
用以標識 RE 於句子中的位置所在. 常見有:
^: 表示句首. 如 ^abc 表示以 abc 開首的句子.
$: 表示句尾. 如 abc$ 表示以 abc 結尾的句子.
\<: 表示詞首. 如 \<abc 表示以 abc 開首的詞.
\>: 表示詞尾. 如 abc\> 表示以 abc 結尾的詞.
- 修飾字符(modifier)
獨立表示時本身不具意義, 專門用以修改前一個 char. set 的出現次數. 常見有:
*: 表示前一個 char. set 的出現次數爲 0 或多次. 如 ab*c 表示 a 與 c 之間可有 0 或多
個 b 存在.
?: 表示前一個 char. set 的出現次數爲 0 或 1 次. 如 ab?c 表示 a 與 c 之間可有 0 或
1 個 b 存在.
+: 表示前一個 char. set 的出現次數爲 1 或多次. 如 ab+c 表示 a 與 c 之間可有 1 或
多個 b 存在.
{n}: 表示前一個 char. set 的出現次數必須爲 n 次. 如 ab{3,}c 表示 a 與 c 之間必須
有 3 個 b 存在.{n,}: 表示前一個 char. set 的出現次數至少爲 n 次. 如 ab{3,}c 表示
a 與 c 之間至少有 3 個 b 存在.
{n,m}: 表示前一個 char. set 的出現次數爲 n 到 m 次. 如 ab{3,5}c 表示 a 與 c 之
間有 3 到 5 個 b 存在.
然而, 當我們在識別 modifier 時, 卻很容易忽略"邊界(boundary)"字符的重要性.
以剛提到的 ab{3,5}c 爲例, 這裏的 a 與 c 就是邊界字符了.
若沒有邊界字符的幫忙, 我們很容以作出錯誤的解讀.
比方說: 我們用 ab{3,5} 這個 RE (少了 c 這個邊界字符)可以抓到 abbbbbbbbbbc (a 後
有 10 個 b )這串字嗎?
從剛纔的 modifier 我們一般會認爲我們要的 b 是 3 到 5 個, 若超出了此範圍, 就不是我
們要表達的.
因此, 我們或會很輕率的認爲這個 RE 抓不到結果...
然而答案卻是可以的! 爲甚麼呢?
讓我們重新解讀 ab{3,5} 這個 RE 看看:
我們要表達的是 a 後接 3 到 5 個 b 即可, 但 3 到 5 個 b 後面我們卻沒規定是甚麼,
因此在 RE 後面可以是任意的文字, 當然包括 b 也可以啦! (明白了嗎?)
同樣的, 我們用 b{3,5}c 也同樣可以抓到 abbbbbbbbbbc 這串字的.
但我們若使用 ab{3,5}c 這樣的 RE 時, 由於同時有 a 與 c 這兩個邊界字符, 那就截然不
同了!
有空再思考一下, 爲何我們用下面這些 RE 都可抓到 abc 這串字呢?
x*
ax*, abx*, ax*b
abcx*, abx*c, ax*bc
bx*c, bcx*, x*bc
...(還有更多...)
但, 若我們在這些 RE 前後分別加一個 ^ 與 $ 這樣的 anchor, 那又如何呢?
剛學 RE 時, 只要能掌握上面這些基本的 meta 大蓋就可以入門了.
一如前述, RE 是一種規範化的文字表達方式, 主要用於某些文字處理工具之間,
如 grep, perl, vi, awk, sed, 等等. 常用以表示一段連續的字符串, 捕獲之或替換之.
然而, 每種工具對 RE 表達式的具體解讀或有一些細微差異, 不過, 基本原則還是一致的.
只要能掌握 RE 的基本原理, 那就一理通百理明瞭, 只是在實作時稍加變通即可.
比方以 grep 來說, 在 Linux 上你可找到 grep, egrep, fgrep 這幾個程序, 其差異大致如
下:
* grep:
傳統的 grep 程序, 在沒有參數的情況下, 只輸出符合 RE 字符串之句子. 常見參數如下:
-v: 逆反模示, 只輸出"不含" RE 字符串之句子.
-r: 遞歸模式, 可同時處理所有層級子目錄裏的文件.
-q: 靜默模式, 不輸出任何結果(stderr 除外. 常用以獲取 return value, 符合爲 true, 否則
爲 false .)
-i: 忽略大小寫.
-w: 整詞比對, 類似 \<word\> .
-n: 同時輸出行號.
-c: 只輸出符合比對的行數.
-l: 只輸出符合比對的文件名稱.
-o: 只輸出符合 RE 的字符串. (gnu 新版獨有, 不見得所有版本都支持.)
-E: 切換爲 egrep .
* egrep:
爲 grep 的擴充版本, 改良了許多傳統 grep 不能或不便的操作. 比方說:
- grep 之下不支持 ? 與 + 這兩種 modifier, 但 egrep 則可.
- grep 不支持 a|b 或 (abc|xyz) 這類"或一"比對, 但 egrep 則可.
- grep 在處理 {n,m} 時, 需用 \{ 與 \} 處理, 但 egrep 則不需.
諸如此類的... 我個人會建議能用 egrep 就不用 grep 啦... ^_^
* fgrep:
不作 RE 處理, 表達式僅作一般字符串處理, 所有 meta 均失去功能.
好了...
關於 RE 的入門, 我暫時就介紹到這裏.
雖然寫得有點亂, 且有些觀念也不很精確, 不過, 姑且算是對大家有一個交差吧.... ^_^
若這兩天還有時間的話, 我再舉些範例來分析一下, 以助大家更好的理解.
假如更有可能的話, 也順道爲大家介紹一下 sed 這個工具.
(啊, 這次我不敢作保證了哦... ^_^ )
----------------
(順道一提: eval )
講到 command line 的重組特性, 真的需要我們好好的加以理解的.
如此便能抽絲剝襺的一層層的將正個 command line 分析得一清二楚, 而不至於含糊.
假如這個重組特性理解下來來, 那麼, 接下來我們介紹一個好玩的命令 --- eval .
我們在不少變量替換的過程中, 常碰到所謂的複式變量的問題, 如:
代碼:
a=1
A1=abc
我們都知道 echo $A1 就可得到 abc 這個結果.
然而, 我們能否用 $A$a 來取代 $A1 而同樣替換出 abc 呢?
這個問題我們可用很輕鬆的用 eval 來解決:
代碼:
eval echo \$A$a
說穿了, eval 只不過是在命令行完成替換重組後, 再來一次替換重組罷了...