正則表達式

爲了充分發揮shell編程的威力,你需要精通正則表達式。 在腳本編程中的一些命令和軟件包普遍使用正則表達式,例如grep, expr, sedawk.

19.1. 一個簡要的正則表達式介紹

一個正式表達式是一個字符串.字符串裏的字符被稱爲元字符,它們可以表示了比它們字面上看起來的意思更豐富的含義。例如,一個引用符號可以表示引用一個人演講中的話,或者表示下面將要講到的引申表示的意思。正則表達式是一個字符或/和元字符組合成的字符集,它們匹配(或指定)一個模式。.

一個正則表達式包含下面一個或多個項:

  • 一個字符集. 這裏的字符集裏的字符表示的就是它們字面上的意思.正則表達式最簡單的情況就是僅僅由字符集組成,而沒有其他的元字符.

  • . 一個錨指明瞭正則表達式在一行文本中要匹配的位置,例如^$就是錨.

  • 修飾符. 它們用於展開或縮小(即是修改了)正則表達式匹配文本行的範圍.修飾符包括了星號,括號和反斜槓符號.

正則表達是的主要作用是用來文本搜索和字串操作。一個正則表達式匹配一個字符或是一串字符--完整的一串字符或是另外一個字符串的子串.

  • 星號 -- * -- 匹配前一個字符的任意多次(包括零次)。

    "1133*"匹配11 + 一個或更多的3 + 可能的其他字符: 113, 1133, 111312, 等等.

  • 點 -- . -- 匹配除了新行符之外的任意一個字符. [1]

    "13." 匹配13 + 至少一個任意字符(包括空格): 1133, 11333, 但不匹配 13 (因爲少了附加的至少一個任意字符).

  • 脫字符 -- ^ -- 匹配一行的開頭,但依賴於上下文環境,可能在正則表達式中表示否定一個字符集的意思.

  • 美元符 -- $ -- 在正則表達式中匹配行尾.

    "^$" 匹配空行.

  • 方括號 -- [...] -- 在正則表達式中表示匹配括號中的一個字符.

    "[xyz]" 匹配字符x, y, 或z.

    "[c-n]" 匹配從字符cn之間的任意一個字符.

    "[B-Pk-y]" 匹配從BP 或從ky的任意一個字符.

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

    "[^b-d]" 匹配除了從bd範圍內所有的字符. 這是正則表達式中反轉意思或取否的一個例子。(就好像在別的情形中!字符所扮演的角色).

    多個方括號字符集組合使用可以匹配一般的單詞和數字模式。"[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).

  • 反斜槓字符 -- \ -- 轉義(escapes) 一個特殊的字符,使這個字符表示原來字面上的意思.

    "\$"表示了原來的字面意思"$",而不是在正則表達式中表達的匹配行尾的意思.同樣,"\\"也被解釋成了字面上的意思"\".

  • 轉義(escape)"尖角號" -- \<...\> -- 用於表示單詞的邊界.

    尖角號必須被轉義,因爲不這樣做的話它們就表示單純的字面意思而已.

    "\<the\>" 匹配單詞"the",但不匹配"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.
     	
  • 擴展的正則表達式. 增加了一些元字符到上面提到的基本的元字符集合裏. 它們在egrep, awk,和Perl中使用.

  • 問號 -- ? -- 匹配零或一個前面的字符. 它一般用於匹配單個字符.

  • 加號 -- + -- 匹配一個或多個前面的字符.它的作用和*很相似,但唯一的區別是它不匹配零個字符的情況.

       1 # GNU 版本的 sed 和 awk 可以使用"+",
       2 # 但它應該轉義一下.
       3 
       4 echo a111b | sed -ne '/a1\+b/p'
       5 echo a111b | grep 'a1\+b'
       6 echo a111b | gawk '/a1+b/'
       7 # 上面三句都是等價的效果.
       8 
       9 # 多謝, S.C.
  • 轉義"大括號" -- \{ \} -- 指示前面正則表達式匹配的次數.

    要轉義是因爲不轉義的話大括號只是表示他們字面上的意思。這個用法只是技巧上的而不是基本正則表達式的內容。

    "[0-9]\{5\}" 精確匹配5個數字 (從 0 到 9的數字).

    大括號不能在“經典”(不是POSIX兼容)的正則表達式版本的awk中使用. 然而, gawk一個選項--re-interval來允許使用大括號(不必轉義).

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

    Perl和一些egrep版本不要求轉義大括號.

  • 圓括號 -- ( ) -- 括起一組正則表達式. 它和下面要講的"|"操作符或在用expr進行子字符串提取(substring extraction)一起使用很有用。

  • 豎線 -- | -- "或"正則操作符用於匹配一組可選的字符.

     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.
     	

一些sed, ed, 和ex的版本像GNU的軟件版本一樣支持上面描述的擴展正則表達式的版本。

  • POSIX字符類. [:class:]

    這是另外一個可選的用於指定匹配字符範圍的方法。

  • [:alnum:] 匹配字母和數字.等同於A-Za-z0-9.

  • [:alpha:] 匹配字母. 等同於A-Za-z.

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

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

  • [:digit:] 匹配(十進制)數字. 等同於0-9.

  • [:graph:] (可打印的圖形字符). 匹配 ASCII 碼值的33 - 126之間的字符. 這和下面提到的 [:print:]一樣,但是不包括空格字符.

  • [:lower:] 匹配小寫字母. 等同於a-z.

  • [:print:] (可打印字符). 匹配 ASCII碼值 32 - 126之間的字符. 這和上面提到的一樣[:graph:],但是增多一個空格字符。

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

  • [:upper:] 匹配大寫字母. 等同於A-Z.

  • [:xdigit:] 匹配十六進制數字. 等同於0-9A-Fa-f.

    POSIX字符類一般都要求用引號或是雙方括號double brackets (` `)引起來.

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

    這些字符類在一個受限的範圍內甚至可能用在能用在通配(globbing)中.

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

    爲了理解POSIX字符類在腳本中的使用,請參考例子 12-18例子 12-19.

Sed, awk, 和Perl在腳本中被用作過濾器, "過濾"或轉換文件/IO流的時候以正則表達式作爲參數。參考例子 A-12例子 A-17 來理解這種用法.

在正則表達式這個複雜主題的標準參考是Friedl的Mastering Regular Expressions.由Dougherty和Robbins寫的 Sed & Awk也給出了一個清晰的正則表達式論述. 查看參考書目 找到這個主題更多的信息.

[1]

因爲Since sed, awk, 和and grep 通常處理單行,而不能匹配一個新行符. 在要處理多行的一個輸入時,可以使用點操作符,它可以匹配新行符。

   1 #!/bin/bash
   2 
   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
  轉自 shell在線中文手冊
  http://manual.51yip.com/shell/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章