介紹
作為系統管理員、開發人員、QA工程師、支援工程師等,我們需要從文件中找到特定的模式,比如屬於某個範圍的一組IP地址,或者一系列時間戳,或者一組域名或子域名。我們可能還需要查找特定方式拼寫的單詞,或者在文件中找到可能的拼寫錯誤。這就是正則表達式的用武之地。
正則表達式是匹配模式(有時是不匹配模式)的模板。它們提供了一種描述和解析文本的方法。本教程將介紹正則表達式的基本概念,而不涉及任何特定語言的細節。我們將簡單地使用egrep來解釋這些概念。
正則表達式
正則表達式由兩種類型的字符組成:
-
常規文字字符和
-
元字符
是正則表達式的強大工具。
考慮以下的 country.txt 檔案,其中第一列是國家名稱,第二列是該國人口,第三列是所在洲。
$ cat country.txt
India,1014003817,Asia
Italy,57634327,Europe
Yemen,1184300,Asia
Argentina,36955182,Latin America
Brazil,172860370,Latin America
Cameroon,15421937,Africa
Japan,126549976,Asia
錨定元字符
我們將討論的第一組”元字符”是 ^ 和 $。 ^ 和 $ 分別匹配模式的開頭和結尾,被稱為 錨定元字符。
要查找所有國家名以 I 開頭的國家名稱,我們使用以下表達式:
$ egrep '^I' country.txt
India,1014003817,Asia
Italy,57634327,Europe
或者要查找所有洲名以 e 結尾的國家,我們可以:
$ egrep 'e$' country.txt
Italy,57634327,Europe
下一個元字符是點(.),它匹配任何一個字符。 要匹配所有國家名恰好為 5 個字符的行:
$ egrep '^.....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Yemen,1184300,Asia
Japan,126549976,Asia
找出所有國家名以 I 或 J 開頭且國家名為 5 個字符長的行該如何處理呢?
$ egrep '^[IJ]....,' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976,Asia
…] 被稱為 字符集 或 字符類。 字符集中只匹配給定字符中的一個。
字符集內的 ^ 否定字符集。以下示例將匹配國家名為五個字符長但不以 I 或 J 開頭的國家名。
$ egrep '^[^IJ]....,' country.txt
Yemen,1184300,Asia
分組元字符和替換
要匹配所有包含亞洲或非洲的行:
$ egrep 'Asia|Africa' country.txt
India,1014003817,Asia
Yemen,1184300,Asia
Cameroon,15421937,Africa
Japan,126549976,Asia
這也可以通過將A和a共同使用來完成。
$ egrep 'A(si|fric)a' country.txt
India,1014003817,Asia
Yemen,1184300,Asia
Cameroon,15421937,Africa
Japan,126549976,Asia
量詞
不是寫
$ egrep '^[IJ]....,' country.txt
我們可以寫
$ egrep '^[IJ].{4},' country.txt
其中{}被稱為量詞。它們決定了它們之前的字符應該出現多少次。
我們也可以給出一個範圍:
$ egrep '^[IJ].{4,6},' country.txt
India,1014003817,Asia
Italy,57634327,Europe
Japan,126549976,Asia
這將匹配以I或J開頭並在其後有4到6個字符的國家名稱。
有一些量詞的快捷方式可用。例如,
{0,1}等同於?
$ egrep '^ab{0,1}c$' filename
等同於
$ egrep '^ab?c' filename
{0,}等同於*
$ egrep '^ab{0,}c$' filename
等同於
$ egrep '^ab*c' filename
{1,}等同於+
$ egrep '^ab{1,}c$' filename
等同於
$ egrep '^ab+c' filename
讓我們看一些涉及到我們迄今所見過的表達式的例子。在這裡,我們不是從文件中搜索,而是從標准輸入中搜索。我們使用的技巧是,我們知道grep(或egrep)搜索一個模式,如果找到一個模式,則顯示包含該模式的整行。
我們想找出句子the grey colour suit was his favourite的所有可能拼法。
該表達式將是:
$ egrep 'the gr[ea]y colou?r suit was his favou?rite'
the grey color suit was his favourite
the grey color suit was his favourite
the gray colour suit was his favorite
the gray colour suit was his favorite
從上面的表達式中可以看出:
-
grey可以拼寫為grey或gray
-
colour可以寫作colour或color,這意味著u是可選的,所以我們使用u?
-
同樣,favourite或favorite可以寫作favou?rite
匹配美國郵政編碼如何?
$ egrep '^[0-9]{5}(-[0-9]{4})?$'
83456
83456
83456-
834562
92456-1234
92456-1234
10344-2342-345
在24小時制時鐘中匹配所有有效時間的另一個例子。
$ egrep '^([01][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]'
23:44:02
23:44:02
33:45:11
15:45:33
15:45:33
在上面的例子中,我們說,如果小時的第一位數是0或1,則第二位數將是0到9中的任意一個。但如果第一位數是2,則第二位數的允許值是0,1,2或3。
單詞邊界
編寫一個模式以匹配以color結尾的單詞,例如unicolor,watercolor,multicolor等,但不匹配colorless或colorful。自己嘗試這些例子,以熟悉它們:
$ egrep 'color\>'
接下來,匹配colorless和colorful,但不匹配unicolor,watercolor,multicolor等。
$ egrep '\<color'
因此,要匹配精確的詞color,我們做:
$ egrep '\<color\>'
反向引用
假設我們想要匹配所有重複輸入的單詞,像the the或before before,我們必須使用反向引用。反向引用用於記住模式。
這是一個例子:
$ egrep "\<the\> \1"
或通用的方法:
$ egrep "\<(.*)\> \1"
上面的例子可以用來找出所有名字,其中名和姓相同。如果有多組括號,則第二、第三、第四等可以用\2、\3、\4等引用。
這只是正則表達式強大功能的介紹。
Source:
https://www.digitalocean.com/community/tutorials/an-introduction-to-regular-expressions