bash – 基本文法教學 #3
正規表示法
正規表示式 ( Regular expressions , 簡稱 regex ) 是一種用來比對文字的方法,相當便利。
在 bash 中,只有複合式指令才會使用到正規表示式,但是還是痕值得學習,因為正規表示式會牽扯到很多工具,像是 grep、awk 和 sed 等等。
範例文件 - frost.txt
1 Two roads diverged in a yellow wood,
2 And sorry I could not travel both
3 And be one traveler,long I stood
4 And looked down one as far as I could
5 To Where it bent in the undergrowth;
6
7 Excerpt from The Road Not Taken by Robert Frosr
正規表示式 - grep
為方便展示,下方使用grep進行正規表示式的講解。grep 指令通常用於檔案內容的搜尋。透過指定樣式,可以比對使否有符合條件的內容。
用法
grep options pattern filenames
(選項) (參數) (檔名)
常用指令
- – c : 計算符合比對樣式的行數。
- -E : 啟用更廣義的正規表示式。
- -f : 從指定檔案讀取要搜尋的樣式。檔案中可以包含多種樣式。一行表示一種樣式。
- -i : 忽略字元大小寫。
- -l : 只印出符合比對樣式的檔案名稱和路徑。
- -n : 印出檔案中符合比對樣式的行號。
- -P : 啟用 Perl 的正規表示式引擎。
- -R,r : 遞迴搜尋子目綠。
舉例
若需要在家目錄和其子目錄搜尋含有 security 字樣的檔案,指令如下所示 :
grep -R -i ‘security’ /home
正規表示式的中介字符
“正規表示式” 其實就是中介字符和很多字元所組合的樣式。
在正規表示式中,有很多特殊符號有特殊意義。
中介字符
句號 ( . )
- 代表單一萬用字元
- 可以比對出任何單一字元,換行字元例外
$ grep ‘T.o’ frost.txt
1 Two roads diverged in a yellow wood,
問號 ( ? )
- 問號會讓它前面的任何項目都變得可有可無
- 允許出現一個、或是沒有項目
$ egrep ‘T.?o’ frost.txt
1 Two roads diverged in a yellow wood,
5 To Where it bent in the undergrowth;
星號 ( * )
- 比對出出現過1次以上、或是根本未出現
- 與 ? 很像,差別在於允許次數一次以上
$ grep ‘T.*o’ frost.txt
1 Two roads diverged in a yellow wood,
5 To Where it bent in the undergrowth;
7 Excerpt from The Road Not Taken by Robert Frosr
加號 ( + )
- 與星號一樣,但必須要求一次以上
- 會比對出出現至少一次的前置樣式
$ egrep ‘T.+o’ frost.txt
1 Two roads diverged in a yellow wood,
5 To Where it bent in the undergrowth;
7 Excerpt from The Road Not Taken by Robert Frosr
群聚
- 透過小括弧來集合字元
- 允許將出現在誇胡中的字元視為事後可以比對參照的單一項目
$ egrep ‘And be one (stranger|traveler), long I stood’ frost.txt
3 And be one traveler,long I stood
中括號和字元種類
中括號通常用來定義字元種類,詳細如下所示 :
- [abc] : 只比對出a、b、c
- [1-5] : 只比對出1~5的數字
- [a-zA-Z] : 只比對出大寫或小寫的英文字母
- [0-9±*/] : 只比對出數字或是四則運算
- [0-9a-fA-F] : 只比對出16進位數字
捷徑
有一系列預先定義好的字元種類,稱之為捷徑
- \s : 空白
- \S : 非空白
- \d : 數字
- \D : 非數字
- \w : 字詞
- \W : 非字詞
- \x : 十六進位數字(例如0x5F
- 需要注意注意, egrep 不支援捷徑
- 需要利用grep -P
一系列字元種類
如果需要對初連續多個字元,可以利用*或是+來製作出需要的效果。
- [:alnum:] – 數字和字母字元
- [:alpha:] – 純字母字元
- [:cntrl:] – 控制字元
- [:digit:] – 數字字元
- [:graph:] – 任何控制和空白字元以外的字元
- [:lower:] – 小寫字母
- [:print:] – 任何控制字元以外的字元
- [:punct:] – 標點符號字元
- [:space:] – 包括換行符號在內的空白字元
- [:upper:] – 大寫字母
- [:xdigit:] - 任何十六進位字元
回朔參照
很好用,但相對比較複雜,需要花一點時間去整理。
範例檔案 tag.txt 如下 :
1 Command
2 <i>line</i>
3 is
4 <div>great</div>
5 <u>!</u>
像這種 html 會被被 HTML標籤包起來的問題,如果需要至找到標籤語言,可以透過回朔功能
- \1 的部分,會回去參考第一個表示式(第一個小括號裡面的)
- \1 代表第一組小括號,\2代表第二組,以此類推
$ egrep ‘<([A-Za-z]*)>.*</\1> tags.txt
<i>line</i>
<div>great</div>
<u>!</u>
定位符號 & 字詞邊界
- 溢出字元(^)就是將樣式鎖在字串開頭
- ^[1-5]代表需要式1到5開頭才算符合
- $字元則是將樣式鎖在結尾
- [1-5]$則是必須1到5做結尾才算符合
- \b 則是用來界定字詞邊界(例如空白)
- \b[1-5]\b 則代表會比對出任何介於空間之間的1到5的數字
相關資源
- http://www.rexegg.com/
- https://regex101.com/
- https://www.regextester.com/
- https://www.regular-expressions.info/