正則表達式(regular expression)一般簡寫爲 regex 或 re,是一種指定字符串模式的簡潔方式。git
圖 20-一、20-二、20-3彙總了正則表達式的使用語法。正則表達式
正則表達式是一種指定字符模式的簡潔方式。在正則表達式中,普通字符匹配自身,特定的元字符擁有特殊的含義。本表列舉了用來執行基本模式匹配的元字符。shell
在正則表達式中,下述元字符稱爲重複運算符,能夠用來匹配多個指定字符的實例。express
注意:一些程序不支持{,m},由於{,m}不是標準的。學習
正則表達式中能夠包含有定義一組字符的字符類。爲了方便起見,正則表達式中有一組預約義字符類,能夠將這些預約義字符類用做字符集合的縮寫。本表示範了最重要的預約義字符類。注意方括號和冒號都是名稱的一部分。spa
最右邊的一列給出了與預約義字符類等價的字符範圍。若是系統使用的是 C 排序序列,則能夠使用這些範圍取代類的名稱。爲了確保系統使用的是 C 排序序列,能夠將環境變量 LC_COLLATE 的值設置爲 C。code
Unix支持兩種主要的正則表達式變體:一個現代版本,一個之前的廢棄版本。現代版本的正則表達式是擴展正則表達式(extended regular expression),或者簡稱爲 ERE。它是當前的標準,疏於 IEEE 1003.2 標準(POSIX 的一部分)。排序
之前版本的正則表達式是基本正則表達式(basic regular expression),或者簡稱爲 BRE。因其功能弱,語法容易混淆,已廢棄。但仍然有時候不得不選擇使用基本正則表達式。(例如,sed 只支持 BRE)字符串
使用擴展正則表達式:grep -E 或 egrepit
圖 20-4,列舉了基本正則表達式的限制,供參考
假定有一個文件 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
假定有一個文件 data,考慮如下用法:
grep 'Har..y' data
grep 'H[aA]' data
grep 'li[cs]en[cs]e' data
grep '\<li[cs]en[cs]e\>' data
有一些字符集是比較常見的,所以他們被冠以相應的名稱,從而方便使用。這些字符集稱爲預約義字符類。
預約義字符類的使用比較直接,除了一個規則以外,這個規則是:方括號其實是名稱的一部分。由於,當時用預約義字符類時,必須包含第二組方括號,以維持正確的語法(當使用字符類時,外面的方括號不屬於類)。
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
此處不單獨闡述。爲了將字典排序序列改變成 C 排序序列,提示如下命令:
export LC_COLLATE=C
export LC_COLLATE=POSIX
setenv LC_COLLATE C
setenv LC_COLLATE POSIX
locale
locale -a
考慮如下命令:
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的話,可能實現不了這種效果。
考慮如下命令:
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
字典文件常見位置:
/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}$'
每當鍵入以文件名做爲參數的命令時,能夠經過使用特定的元字符——通配符(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 將顯示一個適當的消息。
如下是一些例子:
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'