正規表示式和萬用字元的區別
在Shell中,使用在檔案當中搜尋字串的命令,如grep
,awk
,sed
等命令(文字操作三劍客),可以支援正規表示式。
而在系統當中搜尋檔案的命令,如ls
,find
,cp
這些命令不支援正規表示式,所以只能使用萬用字元來進行匹配了。
- 在Shell中只要是匹配字串,都適用於正則匹配。
- 正規表示式匹配的是以一行為單位進行包含匹配的,匹配上就顯示輸出該行文字,否則不顯示。
元字元 | 作用 |
---|---|
* |
匹配前一個字元匹配0次或任意多次。 |
. |
匹配除了換行符外任意一個字元。 |
^ |
匹配行首。例如:^hello 會匹配以hello 開頭的行。 |
$ |
匹配行尾。例如:hello$ 會匹配以hello 結尾的行。 |
[] |
匹配中括號中指定的任意一個字元,只匹配一個字元。 例如: [aoeiu] 匹配意一個母音字母,[0-9] 匹配任意一位數位,[a-z][0-9] 匹配小寫字和一位數位構成的兩位字元。 |
[^] |
匹配除中括號的字元以外的任意一個字元。 例如: [^0-9] 匹配任意一位非數位字元,[^a-z] 表示任意一位非小寫字母。 |
\ |
跳脫符。用於取消將特殊符號的含義取消。 |
\{n\} |
表示其前面的字元恰好出現n次。 例如: [0-9]\{4\} 匹配4位元數位,[1][3-8][0-9]\{9\} 匹配手機號碼。 |
\{n,\} |
表示其前面的字元出現不小於n次。 例如: [0-9]\{2,\} 表示兩位及以上的數位。 |
\{n,m\} |
表示其前面的字元至少出現n次,最多出現m次。 例如: [a-z]\{6,8\} 匹配6到8位元的小寫字母。 |
注意:Shell語言不是一個標準的完整語言,在其他語言中的正規表示式中,是不分基礎正則和擴充套件正則的。而Shell認為你不需要拿正則寫太過複雜的字串篩選格式,所以Shell建議把正規表示式分成基礎正則和擴充套件正則兩種。
建立一個測試檔案test.txt
Seven times have I despised my soul:
——Kahlil Gibran
The first time when I saw her being meek that she might attain height.
The second time when I saw her limping before the crippled.
The third time when she was given to choose between the hard and the easy, and she chose the easy.
The fourth time when she committed a wrong, and comforted herself that others also commit wrong.
The fifth time when she forbore for weakness, and attributed her patience to strength.
The sixth time when she despised the ugliness of a face, and knew not that it was one of her own masks.
And the seventh time when she sang a song of praise, and deemed it a virtue.
(內容為紀伯倫——我曾七次鄙視自己的靈魂)
還有,為了方便檢視,我們可以給grep
命令設定帶有顏色輸出,也就是給grep
命令定義一個別名。
在當前使用者家目錄中的~/.bashrc
檔案中設定grep
命令別名:
# 我們當前的使用者是root使用者
# 執行命令
[root@localhost ~]# vim /root/.bashrc
# 新增內容
alias grep='grep --color=auto'
# 或者
# 針對所有使用者
# echo "alias grep='grep --color=auto'" >>/etc/bashrc
# 針對單個使用者
# echo "alias grep='grep --color=auto'" >>~/.bashrc
這樣在grep
命令執行後的標準輸出中,就會將檔案中匹配的內容標識彩色。
注意:如果在XShell終端修改的~/.bashrc
組態檔,需要關閉當前遠端視窗,重新開啟就可以實現了。
*
練習我們執行如下命令,進行*
匹配練習。
[root@localhost tmp]# grep "k*" test.txt
結果如下:
說明:(重點)
任何字母加上*
,或者說任何符號加上*
,都沒有任何含義,這樣會匹配所有內容,包括空白行。
因為*
的作用是重複前一個字元0次或任意多次。
所以在Shell中的正則中,任何符號加上*
是沒有任何含義的,所有的內容都會被匹配出來。
如果你需要匹配至少包含一個k
字母的行,就需要這樣寫"kk*"
,代表匹配至少包含有一個K
的行,也可以有多個k
。(這行字串一定要有一個k
,但是後面有沒有k
都可以。)
如下圖:
我們可以看到,沒有k
的行,和空行都被過濾掉了。
如果我們需要匹配至少兩個連續的ss
字元,需要執行如下命令:
grep "sss*" test.txt
以此類推。
注意:
正則是包含匹配,只要含有就會列出,所以單獨搜尋一個k
,執行grep "k" test.txt
命令,也能獲得和上面一樣的匹配結果。如下圖:
換句話說,上面這兩種寫法是一個意思,都是搜尋含有k
字母的行,一行中有一個k
字母就可以,有無數個k
字母也可以,都會被匹配出來。
限位(制)符:
如果是上面描述的這種簡單匹配需求,使用哪種方式都可以。
但是有限位(制)符出現的匹配情況,帶*
的方式,處理匹配的情況更豐富。
如下面一段文字:
Stay hungry, stay foolish. ——Steve Jobs
求知若飢,虛心若愚。——喬布斯
Stay hungry, stay folish. ——Steve Jobs
Stay hungry, stay fooolish. ——Steve Jobs
Stay hungry, stay foooolish. ——Steve Jobs
Stay hungry, stay fooooolish. ——Steve Jobs
我們可以看到上端文字中foolish
中有不同數量的o
。(自己隨意錯寫的)
如果我的需求是搜尋foolish
單詞中有三個以上數量o
的行,這個時候就需要限位(制)符了,
其中foolish
單詞中的f
和l
就是限位(制)符的用法。
執行命令如下:
[root@192 tmp]# grep "foooo*lish" test2.txt
結果如下:
說明:其中前三個o
代表固定有三個連續的o
字母出現,最後一個o*
代表可以匹配0次到任意多次個o
字母。
在這種需要有限位(制)符情況下的匹配,加上*
就非常好處理了。
.
練習正規表示式.
匹配除了換行符外任意一個字元。
舉個例子:
文字test2.txt
內容如下:
abc adapt 適應 xyz
abc adopt 採用 xyz
xyz adept 內行 abc
xyz floor 地板 abc
xyz flour 麵粉 abc
d
和t
這兩個字母之間一定有兩個字元的單詞。grep "d..t" test2.txt
*
使用。grep "z.*a" test2.txt
.*
。grep ".*" test2.txt
^
和$
練習正規表示式^
匹配行首,$
匹配行尾。
文字test2.txt
內容如下:
abc adapt 適應 xyz
abc adopt 採用 xyz
xyz adept 內行 abc.
xyz floor 地板 abc
xyz flour 麵粉 abc
^
代表匹配行首,比如^a
會匹配以小寫a
開頭的行。grep "^a" test2.txt
$
代表匹配行尾,如果c$
會匹配以小寫c
結尾的行。grep "c$" test2.txt
^$
則會匹配空白行。grep "^$" test2.txt
grep
命令的-v
選項進行取反,來過濾掉空白行。(標準方式)grep -v "^$" test2.txt
$
結合.
使用。.
結果的行,那是否用.$
來進行匹配呢?rep ".$" test2.txt
.$
中的.
是正則符號的意思,表示匹配除了換行符外任意一個字元。.
結束的行,我們需要在.
前加入跳脫符,把.
變成普通字串,如:\.$
。grep "\.$" test2.txt
說明:
在使用
^
匹配行首,$
匹配行尾的時候,如果使用的是特殊符號開頭或者結尾,我們需要使用跳脫符進行跳脫,再進行匹配。
[]
練習正規表示式[]
匹配中括號中指定的任意一個字元,只匹配一個字元。(注意只能匹配一個字元。)
比如[abc]
要麼會匹配一個a
字元,要麼會匹配一個b
字元,或者要麼會匹配一個c
字元。
文字test.txt
內容如下:
abc adapt 適應 abc
ABC adopt 採用 xyz
abc adept 內行 XYZ
123 floor 地板 ABC
123 flour 麵粉 123
adapt
、adopt
、adept
這三個近似的單詞。grep "ad[ae]pt" test2.txt
[]
比.
的匹配範圍更精準,請根據實際情況,按需使用。[0-9]
會匹配任意一個數位。grep "[0-9]" test2.txt
[A-Z]
會匹配一個大寫字母。grep "[A-Z]" test2.txt
^[a-z]
代表匹配用小寫字母開頭的行。grep "^[a-z]" test2.txt
[^]
練習正規表示式[^]
匹配除中括號的字元以外的任意一個字元。
就相當於在[]
中的內容進行取反。
文字test.txt
內容如下:
abc adapt 適應 abc
ABC adopt 採用 xyz
abc adept 內行 XYZ
123 floor 地板 ABC
123 flour 麵粉 123
grep "[^0-9]" test2.txt
grep "^[^0-9]" test2.txt
rep "[^a-zA-Z]" test2.txt
rep "[^a-zA-Z]$" test2.txt
\{n\}
練習\{n\}
表示其前面的字元恰好出現n次。
提示:\{n\}
中的\
表示跳脫符,下面同理。
如下面一段文字:
Stay hungry, stay foolish. ——Steve Jobs
求知若飢,虛心若愚。——喬布斯
Stay hungry, stay folish. ——Steve Jobs
Stay hungry, stay fooolish. ——Steve Jobs
Stay hungry, stay foooolish. ——Steve Jobs
Stay hungry, stay fooooolish. ——Steve Jobs
o
。grep "o\{3\}" test2.txt
o
,或者包含三個連續o
,都會被匹配到。o
有什麼區別?grep "ooo" test2.txt
\{n\}
方式更為便捷。abc adapt 適應 abc
12a adopt 採用 12345
abc adept 內行 XYZ
1b3 floor 地板 7788999
123 flour 麵粉 123
執行命令:grep "[0-9]\{3\}" test2.txt
\{n\}
的方式進行正則匹配的話,如下:grep "[0-9][0-9][0-9]" test2.txt
[0-9]\{3\}
只能匹配三個連續的數位,而不是匹配四個連續的數位。grep "^[0-9]\{3\}" test2.txt
grep " [0-9]\{3\}$" test2.txt
o
的文字。grep "fo\{3\}l" test2.txt
f
和l
就是限位(制)符。注意:
\{n\}
匹配的方式一般不會用於匹配字母,多用於匹配數位,如電話號碼。還要再重複一遍,正規表示式是包含匹配,多注意限位(制)符的使用。
\{n,\}
練習\{n,\}
表示其前面的字元出現不小於n次。
如下面一段文字:
Stay hungry, stay foolish. ——Steve Jobs
求知若飢,虛心若愚。——喬布斯
Stay hungry, stay folish. ——Steve Jobs
Stay hungry, stay fooolish. ——Steve Jobs
Stay hungry, stay foooolish. ——Steve Jobs
Stay hungry, stay fooooolish. ——Steve Jobs
比如fo\{4,\}l
這個正則就會匹配用f開頭,l結尾,中間最少有4個o的字串。
執行命令:grep "fo\{4,\}l" test2.txt
正則表達是fo\{4,\}l
與ooooo*
的區別同上邊(7)\{n\}
同理。
練習:匹配至少連續5個字數的文字。
abc adapt 適應 abc
12a adopt 採用 12345
abc adept 內行 XYZ
1b3 floor 地板 7788999
123 flour 麵粉 123
執行命令:grep "[0-9]\{4,\}" test2.txt
\{n,m\}
練習\{n,m\}
匹配其前面的字元至少出現n次,最多出現m次。
下面一段文字:
Stay hungry, stay foolish. ——Steve Jobs
求知若飢,虛心若愚。——喬布斯
Stay hungry, stay folish. ——Steve Jobs
Stay hungry, stay fooolish. ——Steve Jobs
Stay hungry, stay foooolish. ——Steve Jobs
Stay hungry, stay fooooolish. ——Steve Jobs
Stay hungry, stay foooooolish. ——Steve Jobs
匹配在字母f和字母l之間有最少3個o
,最多5個o
。
執行命令:grep "fo\{3,5\}l" test2.txt
我們學習Shell的正規表示式,實際的應用是什麼?
提示:要注意區分正規表示式和萬用字元中的符號功能的不同。