2010年1月19日 星期二

樣式比對 (Pattern Matching)

不少 UNIX 的編輯程式都提供搜尋功能,這種功能不限於搜尋特定的字串,而可能是一些特定的符號排列方式。包括 edexvised awk 語言都提供類似功能。UNIX 的指
grep egrep 則專門用來搜尋之用。Pattern ( 樣式 ) 裡可包含一般的字元和一些中
介符號,也稱為常規表示式 ( regular expression)

本章要點如下:

. 檔名與樣式
. 每個程式所接受的中介符號
. 中介符號說明
. 使用範例


檔名與樣式

在展開檔名所使用的中介符號,和樣式比對時所用的中介符號是不一樣的。( 見第四第五兩章 ) 在指令行打入指令時,特殊符號會先經由 shell 處理,然後再傳給程式使用,所以如果未加上引用符號,則會被 shell 誤以為是檔名展開用的中介符號。如以下指令 :

$ grep [A-Z]* chap[12]

可能會被 shell 展開成如下 :

$ grep Array.c Bug.c Comp.c chap1 chap2

然後 grep 會去 Bug.c Comp.c 等等檔案中找 Array.c 這個樣式。若要讓 grep 讀到那些中介符號,則要加上引用符號:

$ grep "[A-Z]*" chap[12]

通常雙引號就可以了,但若要萬無一失,最好用單引號。

( 注意,在樣式 比對 中,? 要尋找的 0 個或是 1 個 常規表示式; 而在檔名展開時,? 代表任何單一字元 )


每個程式所接受的中介符號

此表中,該程式所提供的中介符號下接有個 < 點號 > 以茲標明,說明在後。


<<<<<<<<<<<< 排版請注意,有三個欄位,只翻最後一欄和各欄的標題 >>>>>>>>>>>>>>>>>>

符號               ed ex vi sed awk grep egrep              動作
                                                                                                                              搜尋任何字元
                                                                                                                              搜尋 0 個或是 1 個的前一字元
                                                                                                                              搜尋行開頭
                                                                                                                              搜尋行尾
                                                                                                                              將下一個字元視為一般字元
                                                                                                                              搜尋集合中的任一元素
                                                                                                                              將此樣式儲存起來
                                                                                                                              尋找 n m 次個前一字元
                                                                                                                              尋找字首或字尾的字元
                                                                                                                              尋找前一或多個字元
                                                                                                                              尋找 0 個或 1 個前一字元
                                                                                                                              搜尋分隔符號
                                                                                                                              括號
             
edex sed 中,左邊輸入的是要尋找的樣式,右邊輸入的是取代的樣式。上面的中介符號只在尋找時可用。


p6-3


edex sed 要做取代樣式時,要用下列中介符號:

符號               ed ex sed              動作
                                          將下一字元視為一般字元
                                          取出用 \(\) 儲存的樣式
                                          用前一個搜尋樣式
                                          用前一個取代的樣式
                                          將字元轉成大寫
                                          將字元轉成小寫
                                          將前面的 \U 或是 \L 關閉
                                          將前面的 \u 或是 \l 關閉


中介符號說明

.              尋找除了換行符號外的任一字元
*              尋找 0 個或任意多個的前一字元,前一字元也可是常規表示式。例如 : . 表示任一字元,所以 .*  表示搜尋任何數目的任一字元
^              ^pattern,則尋找出現在行首的 pattern
$              pattern$,尋找在行尾的 pattern
[ ]              搜尋其中的任一字元,可用 - 來表示某個範圍。若在 [] 內的第一個字元用 ^,則表是尋找不符合其中任一元素的 pattern。若將 - 或是 ] 當做第一個字元,則視為集合的一部份,其他任何字元均視為集合的一部份。

\{n,m\}              尋找 n 個到 m 個之前的字元,當然依照慣例,前一個字元可以是常規表示式(regular  expresion)。\{n\} 會尋找恰 n 個前一字元。而 \{n,\} 則尋找至少 n 個。\{n,m\} 則尋找 n 個到 m 個之間的個數,n,m 本身必需在 0-256 的範圍內。

\              將下一個字元的特殊意義關閉。
\{ \}              \{ \} 之間的 pattern 儲存在儲存區中。一行中最多可以儲存 9 pattern。可以用 \1 \9 來取用。
\< \>              尋找字首或字尾的字元
+              尋找一個或多個符號前的常規表示式。
?              尋找 0 個或 1 個符號前的常規表示式。
|              尋找符號前後的常規表示式
( )              尋找在括號內的常規表示式




p6-4


下列只有在取代 pattern 時有意義

\              將下一個字元的特殊意義關閉。
\n              \1 \9 可以來取用前面儲存的 pattern\1 在最左邊
&              將搜尋用的 pattern 代入取代用的 pattern 的一部份
-              將上次的取代用 pattern 做為此次的取代用 pattern
\u              將取代用 pattern 的第一個字元改為大寫
\U              將整個取代 pattern 改為大寫
\l              將取代用 pattern 的第一個字元改為小寫
\L              將整個取代 pattern 改為小寫              



搜尋使用範例


grep egrep 時,pattern 必須用引用符號括起來。若有 $ 符號,則一定要用單引號,如 'pattern' 用於 edexsed awk 時,通常用 / 將常規表示式括起來。下列為使用範例 :

Pattern                            搜尋對象
                                          bag 字串
                                          行開頭為 bag
                                          行尾為 bag
                                          bag 為一行者
                                          Bag 或是 bag
                                          第二個字母為母音者
                                          第二個字母非母音者
                                          第二個字母是任意字元
                                          任何恰有三個字元的行
                                          任何以 . 開頭的行
                                          任何以 . 開頭後面加上兩個小寫字母的行
                                          如上,但僅供 grep sed 使用
                                          任何不以 . 開頭的行
                                          bugbugsbugss 等等
                                          加上引號的單字
                                          加或不加引號的一個單字
                                          一個或多個大寫字母
                                          同上,但僅可用於 egrep awk
                                          單一大寫字母,或後接任意字元
                                          0 個或多個大寫字母
                                          任何字母
                                          任何非字母數字的字元


p6-5



egrep 或是 awk pattern              搜尋對象
                                                                                    56 或是 7
                                                                                    fivesix  或是 seven
                                                                                    808680286 或是 80386
                                                                                    company 或是 companies

ex 或是 vi pattern              搜尋對象
                                                                      theater 或是 the 之類由 the 開頭的單字
                                                                      breathe 或是 the 之類由 the 結尾的單字
                                                                      the 這個單字

sed 或是 grep pattern              搜尋對象
                                                                                    一行中五個以上的 0
                                                                                    尋找 nnn-nn-nnnn 這樣的數字組合





搜尋與取代使用範例

下列為 sed ex 可用的中介符號。ex 指令由 : 開頭。空白表為 tab 表為tab

指令                             結果
                            加上括號後重新執行該行              
                            將一個單字列改為 mv 指令
                            將空白行刪除
                            同上,用於 ex
                            將空白行或是含有空白字元與 tab 的行刪除
                            同上,用於 ex
                            將一個以上的空白字元改成單一空白字元
                            同上,用於 ex
                           
                            將目前行中的數字轉成標籤
                            重覆前一次的取代動作一次
                            同上
                            同上,但同一行搜尋到的都要取代
                            同上
                            對全文進行取代
                            將本行以後的該字均改為大寫
                            將整個檔案全部轉成小寫
                            將本行每個單字的第一個字母改為大寫 ( 可當作標題 )
                            將全文中的某個字改成 no
                            將全文中另一個字改成 no( 用的是上一次的取代 pattern)


p6-6

最後來看看一些把字交換的小技巧。交換兩個字可用下列指令 :

s/die or do/do or die/                            交換兩字

奧妙的地方是用儲存 pattern 的儲存區將 pattern 對調

s/\([Dd]ie\) or \([Dd]o\)/\2 or \1/              將兩個 pattern 對調

沒有留言:

張貼留言

推到 Twitter!
推到 Plurk!
推到 Facebook!