home products tech support contact us

 Linux 技術支援    ⇒   基礎篇    進階篇    補腦篇    指令索引    中⇒ENG
版權所有, 引用請註明出處

正規表示法 Regular Expressions

1.0 正規表示法簡介
1.1 基礎正規表示法(RE/BRE)
        Bracket Expressions(POSIX 中括號表示法)
        POSIX Characters(POSIX 字集)
        .:匹配任何單一字元
        *:匹配前字元從零到無限重複
        ^:匹配起始位置的字串
        $:匹配結束位置的字串
        &:記憶匹配到的字串
        {a,b}:匹配限定重複前字元
        ( ):集合匹配前字串
        < >: 匹配單字
        ( )\1: 向後參考記憶匹配
        |:或匹配
1.2 延伸正規表示法 (ERE)
        |:或匹配
        +:匹配前面一個到無限重複字元
        ?:匹配前面零到一個重複字元


1.0 正規表示法簡介
〝正規表示法〞(Regular Expressions 縮寫為 RE 或 regex 或 regexp)或叫〝正則表達式〞,其作用為:「匹配符合某一規則的字串或字元(字符)」。

例如公司許多的產品目錄,顏色的標示有時用〝color〞有時用〝colour〞,如某天我要搜尋關鍵字〝color〞或〝colour〞如用正規表示法我只要用〝colou*r〞就可找到〝color〞或〝colour〞這兩種拼法,也時常用正規表示法〝\<[^aeiouyAEIOUY]*\>〞來找出無母音的單字來初步檢查看有無打字錯誤,只要花少許時間學習,就能擁有〝正規表示法〞的〝法眼〞很方便和實用。

正規表示法或延伸正規表示法所書寫的匹配敘述叫〝樣板〞(pattern),如上例的〝\<[^aeiouyAEIOUY]*\>〞或〝colou*r〞。

上例只是正規表示法的牛刀小試,正規表示法原本只流行在 UNIX 的一些工具程式如 grep, sed 等,因太強大和好用,故逐漸擴展到其他地方。甚至連微軟在其 Wold/Excel 中也對正規表示法提供了相當程度的支援,故學會了可應用在許多的地方,很值得一學。

<下圖為 MS Word 用正規表示法尋找〝tha〞或〝thi〞>
MS Word wildcard

正規表示法很多人會和萬用字元搞混在一起而分不清,不過這也難怪,因正規表示法和萬用字元所用的符號部分重疊,但所代表的意義卻不一定一樣。更讓人搞混的為 UNIX 自從 1975 年發表了 UNXI V6,其中新增了〝globbing patterns〞(又叫〝glob〞)[註 1.0])擴充了萬用字元語法,從此萬用字元也有 Bracket Expressions 的功能和正規表示法的語法有部分重疊(雖然結果不一定相同)。

萬用字元大多數情況只能操作檔案(例如 ls /dev/[sh]d* ),正規表示法可想像為萬用字元的加強版,還可操作在匹配檔案的內容或程式的輸出(例如 seq 1 999 | grep '5\{2,3\}' ),也更細膩和彈性來匹配某一規則的字串。但正規表示法也有明顯不足的地方;例如正規表示法的語法對地球人來說就像火星文不易閱讀,且外並非所有的指令或工具都有支援正規表示法。

解釋正規表示法之前先舉個例子來說明萬用字元的最大缺點,如下例目的為用萬用字元列出〝/etc〞目錄內第一個字元為大寫的檔案或目錄:

例:

$ cd /etc
$ LANG=POSIX ←設定語系為〝POSIX〞(同等〝LANG=C〞或〝LANG=〞為清除所有設定的語系)
$ ls -d [A-Z]* | head -n 5 ←用萬用字元列出前 5 個第一個字元為大寫的檔案或目錄
ConsoleKit 
DIR_COLORS
Muttrc
DIR_COLORS.xterm 
Muttrc.local  
$ LANG=en_US.UTF-8 ←設定語系為〝en_US.UTF-8〞
$ ls -d [A-Z]* | head -n 5 ←同一動作再作一次
bashrc ←輸出不一樣了?
blkid
bluetooth
bonobo-activation
capi.conf

以上的實驗說明了萬用字元的最大缺點之一,即同一指令在不同的機器或環境輸出會不一樣(不同的語系設定可能會影響萬用字元的排序)。

如果同一功能用 ls 配合有支援正規表示法的 grep 重寫就會有一致的輸出結果,不再有萬用字元因不同環境而影響輸出。

例:
$ cd /etc
$ LANG=POSIX
$ ls -d * | grep '[A-Z].*' | head -n 5 ←用 ls 配合 grep 列出前 5 個第一個字元為大寫的檔案或目錄
ConsoleKit 
DIR_COLORS
DIR_COLORS.xterm
Muttrc
Muttrc.local  
$ LANG=en_US.UTF-8 ←設定語系為〝en_US.UTF-8〞
$ ls -d * | grep '[A-Z].*' | head -n 5 ←再測試看結果
ConsoleKit ←結果一致了
DIR_COLORS
DIR_COLORS.xterm
Muttrc
Muttrc.local

正規表示法本身並不難,但要正確的匹配是需要經驗和多練習, 正規表示法可分 基礎正規表示法(RE) / 延伸正規表示法(ERE),但不同的工具軟體支援的程度不一,如下為 Unix/Linux 常用的工具對正規表示法所支援的程度。

Utility 基礎正規表示法 延伸正規表示法
shell    
vi  
locate  
find
grep
sed
awk


^ back on top ^



 
1.1 基礎正規表示法(RE/BRE)

基礎正規表示法(Basic Regular Expressions)常簡寫為 regex、RE、BRE 或叫〝posix-basic〞。基礎正規表示法為正規表示法中最基本的用法,一般如沒特別說明,正規表示法即指基礎正規表示法;用如 man 查某指令的用法有出現支援〝regexp〞或〝regex〞或〝posix-basic〞就表示有支持基礎正規表示法。

基礎正規表示法對括號中的〝{ }〞, 〝( )〞,〝< >〞和〝|〞視為保留的表示符號(meta-character)有其意義,故要加上跳脫字元,這是和延伸正規表示法(ERE)最明顯的區別。

由於 vi (vim) 編輯器本身就對正規表示法有良好的支援,且如有匹配的字串會反白顯示,故很適合用來練習正規表示法,故以下範例都用 vi 一般模式的搜尋 來實驗。
(如匹配的字串沒反白顯示, 請在 vi 的環境設定中設〝:set hlsearch〞,某些 Linux 發行版如 Fedroa 某些版本,可能還要安裝〝vim-enhanced〞才會反白顯示匹配的文字,Fedroa 使用者可用指今 sudo dnf install vim-enhancedsudo yum install vim-enhanced 來安裝〝vim-enhanced〞)。


請用 vim 輸入如下網路隨機找到的英文繞口令,並存檔為〝re.txt〞,因在介紹 延伸正規表示法grepsed 時可能會再用到(如懶的輸入就用複製-貼上)

(vi 編輯)
busy buzzing bumblebees buzzing busying
6 silly sisters selling shining shoes
The driver was drunk and drove the doctor's car into deep ditch.
can you can a can as a canner can can a can

google Goggles Solves SUDOKU Puzzles.
How much oil boil can a gum boil boil if a gum boil can boil oil?
Where's the peck of pickled peppers Peter Piper picked?
55 Flags freely flutter from the floating frigate


^ back on top ^

1.2 延伸正規表示法(ERE)

但為什麼要有〝延伸正規表示法〞呢?個人認為(個人認為不一定對,有空我再考證一下)因基礎正規表示法在定義的時候漏掉了或匹配的〝|〞。

為什要為了一個或匹配符號的〝|〞而定義延伸正規表示法?符號〝|〞這麼重要嗎?是的!!舉簡單的例子,假設我不用〝|〞,但我要匹配單字〝as〞或〝if〞我可能可寫成〝[ai][sf]〞但此時你要保佑不要匹配到單字〝is〞。

但隨便增加或匹配符號的〝|〞到基礎正規表示法會有相容問題,如以前寫的 pattern 只是要匹配字元〝|〞但並不是要進行或匹配運算。 故解決方法為原基礎正規表示法要用或匹配要加跳脫字元寫成〝\|〞 另新增另一表示法叫〝延伸正規表示法〞則直接用〝|〞表示或匹配也順便修改了些東東。

延伸正規表示法(Extended Regular Expressions)或叫〝posix-Extended〞常簡寫為 ERE,和基礎正規表示法不同的地方如下。

所以延伸正規表示法也沒什特別不是嗎?一般來說指令如有支援延伸正規表示法,且要指定用延伸正規表示法來匹配時其選項為〝-E〞,例如 grep -E 。而 grep 也是支援延伸正規表示法的典行指令。

延伸正規表示法新增的項目如下:


^ back on top ^




[註1.0]〝globbing patterns〞(又叫〝glob〞)中文好像有人叫〝通配〞,目的為類似萬用字元來匹配字串,用因年代久遠,連〝glob〞這一辭如何而來的都已不可考。

[註1.1]
下表為 ASCII table (資料來源 http://www.asciitabl)
Dec Hex 縮寫 Linux 常用的表示方式 名稱/意義 Dec Hex 顯示字元 Dec Hex 顯示字元 Dec Hex 顯示字元
0 0 NUL   空字元(Null) 32 20 (空格) 65 41 A 98 62 b
1 1 SOH   標題開始 (start of heading) 33 21 ! 66 42 B 99 63 c
2 2 STX   本文開始 (star of text)   34 22 " 67 43 C 100 64 d
3 3 ETX   本文結束 (end of text) 35 23 #   68 44 D   101 65 e
4 4 EOT   傳輸結束 (end of transmission) 36 24 $ 69 45 E 102 66 f
5 5 ENQ   請求 (enquiry) 37 25 % 70 46 F 103 67 g
6 6 ACK   請求確認 (acknowledge) 38 26 & 71 47 G 104 68 h
7 7 BEL \a 響鈴 (bell) 39 27 ' 72 48 H 105 69 i
8 8 BS \b 退格 (backspace) 40 28 ( 73 49 I 106 6A j
9 9 TAB \t 水平定位 (horizontal tab) 41 29 ) 74 4A J 107 6B k
10 0A LF \n 換行 (line feed,new line) 42 2A * 75 4B K 108 6C l
11 0B VT \v 垂直定位 (vertical tab) 43 2B + 76 4C L 109 6D m
12 0C FF \f 換頁 (NP form feed, new page) 44 2C , 77 4D M 110 6E n
13 0D CR \r 回車 (carriage return) 45 2D - 78 4E N 111 6F o
14 0E SO   移出(Shift out) 46 2E . 79 4F O 112 70 p
15 0F SI   移入(Shift in) 47 2F / 80 50 P 113 71 q
16 10 DLE   跳出資料連結 (data link escape) 48 30 0 81 51 Q 114 72 r
17 11 DC1   設備控制一(device ctrl. 1)
(XON 啟用軟體速度控制)
49 31 1 82 52 R 115 73 s
18 12 DC2   設備控制二 (device ctrl. 2) 50 32 2 83 53 S 116 74 t
19 13 DC3   設備控制三 (device ctrl. 3)
(XOFF 停用軟體速度控制)
51 33 3 84 54 T 117 75 u
20 14 DC4   設備控制四 (device ctrl. 4) 52 34 4 85 55 U 118 76 v
21 15 NAK   失敗確認 (negative ack.) 53 35 5 86 56 V 119 77 w
22 16 SYN   暫停同步 (syn. idle) 54 36 6 87 57 W 120 78 x
23 17 ETB   結束區塊傳輸 (end of trans. block) 55 37 7 88 58 X 121 79 y
24 18 CAN   取消 (cancel) 56 38 8 89 59 Y 122 7A z
25 19 EM   媒介中斷 (end of medium) 57 39 9 90 5A Z 123 7B {
26 1A SUB   替換 (substitute) 58 3A : 91 5B [ 124 7C |
27 1B ESC   結束 (escape) 59 3B ; 92 5C \ 125 7D }
28 1C FS   檔案分割 (file separator) 60 3C < 93 5D ] 126 7E ~
29 1D GS   群組分隔 (group separator) 61 3D = 94 5E ^ 127 7F DEL
(不會顯示)
30 1E RS   記錄分隔 (record separator) 62 3E > 95 5F _
31 1F US   單元分隔 (unit separator) 63 3F ? 96 60 `
127 7F DEL   刪除 (delete)   64 40 @ 97 61 a