正則表達式

1. 綜述

正則表達式(regular expression)一般簡寫爲 regex 或 re,是一種指定字符串模式的簡潔方式。git

圖 20-一、20-二、20-3彙總了正則表達式的使用語法。正則表達式

正則表達式是一種指定字符模式的簡潔方式。在正則表達式中,普通字符匹配自身,特定的元字符擁有特殊的含義。本表列舉了用來執行基本模式匹配的元字符。shell

在正則表達式中,下述元字符稱爲重複運算符,能夠用來匹配多個指定字符的實例。express

注意:一些程序不支持{,m},由於{,m}不是標準的。學習

正則表達式中能夠包含有定義一組字符的字符類。爲了方便起見,正則表達式中有一組預約義字符類,能夠將這些預約義字符類用做字符集合的縮寫。本表示範了最重要的預約義字符類。注意方括號和冒號都是名稱的一部分。spa

最右邊的一列給出了與預約義字符類等價的字符範圍。若是系統使用的是 C 排序序列,則能夠使用這些範圍取代類的名稱。爲了確保系統使用的是 C 排序序列,能夠將環境變量 LC_COLLATE 的值設置爲 C。code

2. 基本和擴展正則表達式

Unix支持兩種主要的正則表達式變體:一個現代版本,一個之前的廢棄版本。現代版本的正則表達式是擴展正則表達式(extended regular expression),或者簡稱爲 ERE。它是當前的標準,疏於 IEEE 1003.2 標準(POSIX 的一部分)。排序

之前版本的正則表達式是基本正則表達式(basic regular expression),或者簡稱爲 BRE。因其功能弱,語法容易混淆,已廢棄。但仍然有時候不得不選擇使用基本正則表達式。(例如,sed 只支持 BRE字符串

使用擴展正則表達式:grep -E 或 egrepit

圖 20-4,列舉了基本正則表達式的限制,供參考

3. 匹配單詞和行

假定有一個文件 data,考慮如下用法:

  • grep '^Harley' data

  • grep 'Harley$' data

  • grep '^Harley$' data

  • grep '^$' data | wc -l

  • grep '\<kn' data

  • grep 'ow\>' data

  • grep '\<know\>' data

下述3條命令都是等價的:

  • grep -w 'cat' data

  • grep '\<cat\>' data

  • grep '\bcat\b' data

4. 匹配字符:字符類

假定有一個文件 data,考慮如下用法:

  • grep 'Har..y' data

  • grep 'H[aA]' data

  • grep 'li[cs]en[cs]e' data

  • grep '\<li[cs]en[cs]e\>' data

5. 預約義字符類:範圍

有一些字符集是比較常見的,所以他們被冠以相應的名稱,從而方便使用。這些字符集稱爲預約義字符類

預約義字符類的使用比較直接,除了一個規則以外,這個規則是:方括號其實是名稱的一部分。由於,當時用預約義字符類時,必須包含第二組方括號,以維持正確的語法(當使用字符類時,外面的方括號不屬於類)。

  • grep '21[[:alpha:]]' data

  • grep '[[:upper:]][[:upper:]][[:digit:]][[:lower:]]' data

  • grep '[3-7]' data

  • grep 'X[0-9][0-9]' data grep 'X[[:digit:]][[:digit:]]' data 

  • grep 'X[^ao]' data

  • grep '[^A-Za-z]' data

  • grep '[^[:alpha:]]' data

6. 區域設置和排序序列

此處不單獨闡述。爲了將字典排序序列改變成 C 排序序列,提示如下命令:

  • export LC_COLLATE=C

  • export LC_COLLATE=POSIX

  • setenv LC_COLLATE C

  • setenv LC_COLLATE POSIX

  • locale

  • locale -a

7. 使用範圍和預約義字符類

考慮如下命令:

  • grep 'H[[:lower:]]' data

  • grep 'H[a-z]' data

  • grep '[A-Za-z][0-9][a-z]' data

  • grep '[[:alpha:]][[:digit:]][[:lower:]]' data

  • grep '[A-Z][0-9][A-Z] [0-9][A-Z][0-9]'

  • data grep '[[:upper:]][[:digit:]][[:upper:]] [[:digit:]][[: upper:]][[:digit:]]' data

選擇使用哪種類型的字符類——是範圍仍是預約義名稱——由本身決定。許多之前的 Unix 用戶傾向於使用範圍,由於他們學習得就是範圍。此外,範圍還比名稱更容易鍵入。

可是,名稱更可讀,從而使得它們更適合在 shell 腳本中使用。另外,無論使用哪種區域設置或語言,名稱老是正確的,所以它們的移植性更出色。例如,假設處理的文本中包含非英語字符,如 é(有重音符的 e)。經過使用 [:lower:],就能夠確保獲取 é。可是,若是使用a-z的話,可能實現不了這種效果。

8. 重複運算符

考慮如下命令:

  • grep 'H[a-z]*' data

  • grep 'H[[:lower:]]*' data 

  • grep 'error.*code' data

  • grep ':.*:' data

  • grep 'variable[0-9]+' data

  • grep 'variable[[:digit:]]+' data

  • grep '[vV]ariable[0-9]+' data

  • grep 'colou?r' data

  • grep '\<[0-9]{2,3}\>' data

  • grep 'cat|dog|bird|hamster' data

  • grep '\<(cat|dog|bird|hamster)\>' data

  • grep '\$' data

  • grep '\\\*.*[A-Za-z]+\$' data

10. 解決3個有趣的難題

字典文件常見位置:

  • /usr/share/dict/words

  • /usr/dict/words

  • /usr/share/lib/dict/words

1. 哪些英語單詞以「qu」開頭並以「y」結尾?

  • grep '^qu[a-z]+y$' /usr/share/dict/words

2. 查找一個包含全部 5 個元音字母 a、e、i、o、u(而且以該順序出現)的普通英語單詞。這 5 個字母沒必要連在一塊兒,可是它們必須按字母表順序出現。

  • grep 'a[a-z]*e[a-z]*i[a-z]*o[a-z]*u' /usr/share/dict/words

3. 查找全部兩個字母長的 Unix 命令

  • ls /bin | grep '^[a-z]{2}$' 

  • ls /bin | egrep '^[a-z]{2}$' 

  • ls /bin | grep '^[a-z][a-z]$'

  • ls /usr/bin | grep '^[a-z]{2}$'

  • ls /bin | grep -c '^[a-z]{2}$'

  • ls /usr/bin | grep -c '^[a-z]{2}$' 

附錄1. 通配符

每當鍵入以文件名做爲參數的命令時,能夠經過使用特定的元字符——通配符(wildcard)——指定多個文件名。元字符是由shell 解釋時擁有特殊含義的字符。當在文件名中使用通配符時,通配符就擁有特殊的含義。

乍一看,通配符和正則表達式元字符及其類似。實際上,通配符更加簡單一些。此外,它們只有一個用途:當鍵入一條命令時匹配一組文件名。

圖 24-5 列出了基本的通配符及其含義。注意:當鍵入路徑名時,不能匹配 / 字符,該字符必須顯示鍵入。

根據所使用的 shell 的類型不一樣,使用通配符指定文件的正式稱呼也有所不一樣。在 Bash 中,稱之爲路徑名擴展(pathname expansion);在 Korn shell 中,稱之爲文件名生成(filename generation);在 C-Shell 或 Tcsh 中,稱之爲文件名替換(filename substitution)。當 shell 執行實際替換時,稱之爲通配(globbing)

通配符能夠使用範圍匹配指定字符集中的字符。最多見的包括 [a-z] 匹配小寫字母,[A-Z] 匹配大寫字母。這類範圍適用於 C 區域設置,而不適用於 en-US 區域設置。做爲備選方法,能夠使用預約義字符類替代範圍。圖 24-6 中列舉了一些最重要的預約義字符類。

一些例子:

  • ls h*

  • ls /bin/[a-z][a-z] /usr/bin/[a-z][a-z] 

  • ls /bin/[[:lower:]][[:lower:]] /usr/bin/[[:lower:]][[:lower:]]

  • ls /home/{harley,weedly,tln}

  • cat olddata1 olddata2 olddata3 newdata1 newdata2 newdata3 > master

  • cat {old,new}data{1,2,3} > master

  • cat {old,new}data[1-3] > master

  • mkdir ~/work/essays ~/work/photos ~/work/bin ~/work/music

  • mkdir ~/work/{essays,photos,bin,music}

  • touch data{old,new,backup,master,final}

正如前面所述,當 shell 匹配通配符時,在參數傳遞給程序以前,通配符已變成實際文件名。若是使用的模式不匹配任何文件,那麼 shell 將顯示一個適當的消息。

附錄2. grep 重要的選項

如下是一些例子:

  • ls -F /etc | grep -c "/" 

  • grep -i pizza food-costs 

  • grep -in pizza food-costs

  • grep -l Harley names oldnames newnames

  • grep -L Harley names oldnames newnames

  • grep -w now memo 

  • grep -v DONE homework 

  • grep -cv DONE homework 

  • grep -x Harley names

  • grep -r initialize admin 

  • grep -rs / 'shutdown now'

附錄3. 補充

  • \s:匹配任意的空白符
  • \S:匹配任意不是空白符的字符
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息