正則表達(dá)式就是由一系列特殊字符組成的字符串, 其中每個(gè)特殊字符都被稱為元字符, 這些元字符并不表示為它們字面上的含義, 而會(huì)被解釋為一些特定的含義. 具個(gè)例子, 比如引用符號(hào), 可能就是表示某人的演講內(nèi)容, 同上, 也可能表示為我們下面將要講到的符號(hào)的元-含義. 正則表達(dá)式其實(shí)是由普通字符和元字符共同組成的集合, 這個(gè)集合用來匹配(或指定)模式.

一個(gè)正則表達(dá)式會(huì)包含下列一項(xiàng)或多項(xiàng):

  • 一個(gè)字符集. 這里所指的字符集只包含普通字符, 這些字符只表示它們的字面含義. 正則表達(dá)式的最簡(jiǎn)單形式就是包含字符集, 而不包含元字符.

  • . 指定了正則表達(dá)式所要匹配的文本在文本行中所處的位置. 比如, ^, 和$就是錨.

  • 修飾符. 它們擴(kuò)大或縮小(修改)了正則表達(dá)式匹配文本的范圍. 修飾符包含星號(hào), 括號(hào), 和反斜杠.

正則表達(dá)式最主要的目的就是用于(RE)文本搜索與字符串操作. (譯者注: 以下正則表達(dá)式也會(huì)被簡(jiǎn)稱為RE.) RE能夠匹配單個(gè)字符或者一個(gè)字符集 -- 即, 一個(gè)字符串, 或者一個(gè)字符串的一部分.

  • 星號(hào) -- * -- 用來匹配它前面字符的任意多次, 包括0次.

    "1133*"匹配11 + 一個(gè)或多個(gè)3 + 也允許后邊還有其他字符: 113, 1133, 111312, 等等.

  • 點(diǎn) -- . -- 用于匹配任意一個(gè)字符, 除了換行符. [1]

    "13." 匹配13 + 至少一個(gè)任意字符(包括空格): 1133, 11333, 但不能匹配13 (因?yàn)槿鄙?."所能匹配的至少一個(gè)任意字符).

  • 脫字符號(hào) -- ^ -- 匹配行首, 但是某些時(shí)候需要依賴上下文環(huán)境, 在RE中, 有時(shí)候也表示對(duì)一個(gè)字符集取反.

  • 美元符 -- $ -- 在RE中用來匹配行尾.

    "XXX$" 匹配行尾的XXX.

    "^$" 匹配空行.

  • 中括號(hào) -- [...] -- 在RE中, 將匹配中括號(hào)字符集中的某一個(gè)字符.

    "[xyz]" 將會(huì)匹配字符x, y, 或z.

    "[c-n]" 匹配字符c到字符n之間的任意一個(gè)字符.

    "[B-Pk-y]" 匹配從BP, 或者從ky之間的任意一個(gè)字符.

    "[a-z0-9]" 匹配任意小寫字母或數(shù)字.

    "[^b-d]" 將會(huì)匹配范圍在bd之外的任意一個(gè)字符. 這就是使用^對(duì)字符集取反的一個(gè)實(shí)例. (就好像在某些情況下, !所表達(dá)的含義).

    將多個(gè)中括號(hào)字符集組合使用, 能夠匹配一般的單詞或數(shù)字. "[Yy][Ee][Ss]"能夠匹配yes, Yes, YES, yEs, 等等. "[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]" 可以匹配社保碼(Social Security number).

  • 反斜杠 -- \ -- 用來轉(zhuǎn)義某個(gè)特殊含義的字符, 這意味著, 這個(gè)特殊字符將會(huì)被解釋為字面含義.

    "\$"將會(huì)被解釋成字符"$", 而不是RE中匹配行尾的特殊字符. 相似的, "\\"將會(huì)被解釋為字符"\".

  • 轉(zhuǎn)義"尖括號(hào)" -- \<...\> -- 用于匹配單詞邊界.

    尖括號(hào)必須被轉(zhuǎn)義才含有特殊的含義, 否則它就表示尖括號(hào)的字面含義.

    "\<the\>" 完整匹配單詞"the", 不會(huì)匹配"them", "there", "other", 等等.

     

    bash$ cat textfile
    This is line 1, of which there is only one instance.
    This is the only instance of line 2.
    This is line 3, another line.
    This is line 4.



    bash$ grep 'the' textfile
    This is line 1, of which there is only one instance.
    This is the only instance of line 2.
    This is line 3, another line.



    bash$ grep '\<the\>' textfile
    This is the only instance of line 2.
  • 擴(kuò)展的正則表達(dá)式. 添加了一些額外的匹配字符到基本集合中. 用于egrep, awk, 和Perl.

  • 問號(hào) -- ? -- 匹配它前面的字符, 但是只能匹配1次或0次. 通常用來匹配單個(gè)字符.

  • 加號(hào) -- + -- 匹配它前面的字符, 能夠匹配一次或多次. 與前面講的*號(hào)作用類似, 但是不能匹配0個(gè)字符的情況.

      1 # GNU版本的sed和awk能夠使用"+",
    2 # 但是它需要被轉(zhuǎn)義一下.

    4 echo a111b | sed -ne '/a1\+b/p'
    5 echo a111b | grep 'a1\+b'
    6 echo a111b | gawk '/a1+b/'
    7 # 上邊3句的作用相同.

    9 # 感謝, S.C.
  • 轉(zhuǎn)義"大括號(hào)" -- \{ \} -- 在轉(zhuǎn)義后的大括號(hào)中加上一個(gè)數(shù)字, 這個(gè)數(shù)字就是它前面的RE所能匹配的次數(shù).

    大括號(hào)必須經(jīng)過轉(zhuǎn)義, 否則, 大括號(hào)僅僅表示字面含意. 這種用法并不是基本RE集合中的一部分, 僅僅是個(gè)技巧而以.

    "[0-9]\{5\}" 精確匹配5個(gè)數(shù)字 (所匹配的字符范圍是0到9).

    Note

    使用大括號(hào)形式的RE是不能夠在"經(jīng)典"(非POSIX兼容)的awk版本中正常運(yùn)行的. 然而, gawk命令中有一個(gè)--re-interval選項(xiàng), 使用這個(gè)選項(xiàng)就允許使用大括號(hào)形式的RE了(無需轉(zhuǎn)義).

     

    bash$ echo 2222 | gawk --re-interval '/2{3}/'
    2222

    Perl與某些版本的egrep不需要轉(zhuǎn)義大括號(hào).

  • 圓括號(hào) -- ( ) -- 括起一組正則表達(dá)式. 當(dāng)你想使用expr進(jìn)行子字符串提取(substring extraction)的時(shí)候, 圓括號(hào)就有用了. 如果和下面要講的"|"操作符結(jié)合使用, 也非常有用.

  • 豎線 -- | -- 就是RE中的"或"操作符, 使用它能夠匹配一組可選字符中的任意一個(gè).

     

    bash$ egrep 're(a|e)d' misc.txt
    People who read seem to be better informed than those who do not.
    The clarinet produces sound by the vibration of its reed.

Note

與GNU工具一樣, 某些版本的sed, ed, 和ex一樣能夠支持?jǐn)U展正則表達(dá)式, 上邊這部分就描述了擴(kuò)展正則表達(dá)式.

  • POSIX字符類. [:class:]

    這是另外一種, 用于指定匹配字符范圍的方法.

  • [:alnum:] 匹配字母和數(shù)字. 等價(jià)于A-Za-z0-9.

  • [:alpha:] 匹配字母. 等價(jià)于A-Za-z.

  • [:blank:] 匹配一個(gè)空格或是一個(gè)制表符(tab).

  • [:cntrl:] 匹配控制字符.

  • [:digit:] 匹配(十進(jìn)制)數(shù)字. 等價(jià)于0-9.

  • [:graph:] (可打印的圖形字符). 匹配ASCII碼值范圍在33 - 126之間的字符. 與下面所提到的[:print:]類似, 但是不包括空格字符(空格字符的ASCII碼是32).

  • [:lower:] 匹配小寫字母. 等價(jià)于a-z.

  • [:print:] (可打印的圖形字符). 匹配ASCII碼值范圍在32 - 126之間的字符. 與上邊的[:graph:]類似, 但是包含空格.

  • [:space:] 匹配空白字符(空格和水平制表符).

  • [:upper:] 匹配大寫字母. 等價(jià)于A-Z.

  • [:xdigit:] 匹配16進(jìn)制數(shù)字. 等價(jià)于0-9A-Fa-f.

    Important

    POSIX字符類通常都要用引號(hào)或雙中括號(hào)([[ ]])引起來.

     

    bash$ grep [[:digit:]] test.file
    abc=723

    如果在一個(gè)受限的范圍內(nèi), 這些字符類甚至可以用在通配(globbing)中.

     

    bash$ ls -l ?[[:digit:]][[:digit:]]?
    -rw-rw-r-- 1 bozo bozo 0 Aug 21 14:47 a33b

    如果想了解POSIX字符類在腳本中的使用情況, 請(qǐng)參考例子 12-18例子 12-19.

Sed, awk, 和Perl在腳本中一般都被用作過濾器, 這些過濾器將會(huì)以RE為參數(shù), 對(duì)文件或者I/O流進(jìn)行"過濾"或轉(zhuǎn)換. 請(qǐng)參考例子 A-12例子 A-17, 來詳細(xì)了解這種用法.

對(duì)于RE這個(gè)復(fù)雜的主題, 標(biāo)準(zhǔn)的參考材料是Friedl的Mastering Regular Expressions. 由Dougherty和Robbins所編寫的Sed & Awk這本書, 也對(duì)RE進(jìn)行了清晰的論述. 如果想獲得這些書的更多信息, 請(qǐng)察看參考文獻(xiàn).

注意事項(xiàng)

[1]

因?yàn)?a >sed, awk, 和grep通常用于處理單行, 但是不能匹配一個(gè)換行符. 如果你想處理多行輸入的話, 那么你可以使用"點(diǎn)"來匹配換行符.

  1 #!/bin/bash

3 sed -e 'N;s/.*/[&]/' << EOF # Here Document
4 line1
5 line2
6 EOF
7 # 輸出:
8 # [line1
9 # line2]
10 
11 
12 
13 echo
14 
15 awk '{ $0=$1 "\n" $2; if (/line.1/) {print}}' << EOF
16 line 1
17 line 2
18 EOF
19 # 輸出:
20 # line
21 # 1
22 
23 
24 # 感謝, S.C.
25
26 exit 0