【個人Linux,我作主!】通配符和正則表達式深層解析

目錄:
(一)瞭解通配符和正則的做用
(二)通配符的使用
(三)正則表達式的使用
(四)擴展正則表達式的使用git


(一)瞭解通配符和正則的做用
(1.1)在咱們平常的工做中,咱們都會使用到通配符或者正則表達式。通配符是一種特殊語句,主要有星號(*)和問號(?),用來模糊搜索文件。當查找文件夾時,可使用它來代替一個或多個真正字符;當不知道真正字符或者懶得輸入完整名字時,經常使用通配符代替一個或多個真正的字符。正則表達式是計算機科學的一個概念,正則表達式一般被用來檢索、替換那些符合某個模式的文本,正則表達式是對字符串操做的一種邏輯公式,就是用事先定義好的一些特定字符、及這些特定字符的組合,組成一個「規則字符串」,這個「規則字符串」用來表達對字符串的一種過濾邏輯。
(1.2)不論是通配符仍是正則表達式,其功能都是實現模糊匹配,用來匹配某一類東西,並非匹配具體的某一個值。通配符通常用於shell中,正則表達式通常用於其餘語言。正則表達式


(二)通配符的使用
(2.1)首先第一個是「[]」中括號[list],匹配的是list中的任意單一字符。例如a[xyz]b,a與b之間必須也只能有一個字符,但只能是x或y或z,如:axb,ayb,azb
(2.2)第二個是「[c1-c2]」,用來表示字符的範圍,匹配c1-c2的任意單一字符,如[0-9]或[a-z]。例如「a[0-9]b」表示的是0到9之間必須也只能有一個字符,如:a0b、a1b、a2b、a3b、a4b、a5b、a6b、a7b、a8b、a9b
注意:若是咱們須要匹配的是單個字母,且不分大小寫,則咱們可使用「[a-zA-Z]」來進行表示。
(2.3)第三個是「[!c1-c2]或[^c1-c2]」,匹配的是不在c1-c2的任意字符。例如a[!0-9]b,a[^0-9]b表示a與b之間只有一個字符,而且不是數字0-9之間的字符,符合要求的有:acb、adb
(2.4)示例:咱們在vms002主機上建立一個rh124目錄,而後在rh124目錄中建立相關的文件:111十一、a1十一、a_1十一、a2二、lwang、lWang、rh124。接着咱們查詢第一個字符時a到z之間的,第二個字符是非數字的,後面的字符都是任意的。
# mkdir rh124
# touch 11111 a111 a_111 a22 lwang lWang rh124
# ls [a-z][^0-9]*---查詢第一個字符時a到z之間的,第二個字符是非數字的,後面的字符都是任意的
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(2.5)示例:接着咱們的需求是在rh124目錄下找到格式爲第一個字符是a到z之間,第二個字符是a或者「-」或者z三個字符中的任意一個,後面的字符是任意的。這樣咱們就能夠符合要求的文件名a-1
# touch a-1
# ls [a-z][a-z]*
【個人Linux,我作主!】通配符和正則表達式深層解析
(2.6)第四個是精確指定字符的大小寫「[[:upper:]]」、「[[:lower:]]」,因爲咱們使用[a-z]的時候可能會匹配出a到z和A到Z之間的字符,大小寫並不能精確匹配,因此咱們可使用「[[:upper:]]」表示純大寫的字符,咱們可使用「[[:lower:]]」表示純小寫的字符。
# ls [[:upper:]]*---查詢全部純大寫字目開頭的文件名
# ls [[:lower:]]*---查詢全部純小寫字母開頭的文件名
【個人Linux,我作主!】通配符和正則表達式深層解析
(2.7)固然第四個精確指定字符中仍是有其餘表示特定字符的方式的:「[[:alpha:]]」表示的是隻匹配字母,「[[:alnum:]]」表示的是匹配字母和數字,「[[:digit:]]」表示的是匹配純數字。
(2.8)示例:如今咱們的系統中沒有marry用戶,咱們首先建立一個marry用戶,而且指定在根下建立marry的家目錄(圖1-5)。而後咱們將marry家目錄刪除,此時咱們切換到marry用戶後發現因爲沒有家目錄,因此切換後是異常的狀態(圖1-6),此時咱們在/etc/default/useradd配置文件中,查詢到用戶家目錄的模板文件在/etc/skel的目錄中(圖1-7),咱們將/etc/skel中的全部模板文件都拷貝到marry家目錄下,並修改了屬主和屬組的相關信息,此時即可以正常的進行marry用戶的切換了(圖1-8)。
# useradd -d /marry marry---建立一個marry用戶,而且指定在根下建立marry的家目錄
# rm -rf /marry/---刪除marry的家目錄
# vim /etc/default/useradd---查詢/etc/default/目錄下的useradd文件
# cp -a /etc/skel/.[^.]* /marry/---將/etc/skel/目錄下的全部以「.」開頭,第二個字符因爲是「[]」因此必需要存在並且是非「.」號,後面跟任意字符的文件所有拷貝到/marry家目錄下,skel表示骨架、框架(圖1-8)
# chown -R marry.marry /marry/---修改/marry家目錄的全部者和所屬組都爲marry(圖1-8)
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(2.9)第五個是「?」問號,匹配的是任意一個字符。例如在rh124目錄中,咱們查詢「[a-z]????」,表示的是查詢第一個字符是字母構成,後面會有四個任意的字符構成的文件名。
注意:「?」問號是不能匹配到表示隱藏文件的「.」點號的。即表示若是如今系統中有「.aa」文件,咱們使用「???」是不能匹配出這個隱藏文件的,若是咱們想要匹配出這類隱藏文件則應該開啓全局通配符處理。
# ls [a-z]????---查詢第一個字符是字母構成,後面會有四個任意的字符構成的文件名
【個人Linux,我作主!】通配符和正則表達式深層解析
(2.10)第六個是「*」星號,表示匹配任意長度的任意字符。例如咱們將全部文件名以a字母開頭,且後面是任意字符的文件都刪除掉
# touch aaa bb cc aa2---建立以下的四個文件
# rm -rf a*---將全部文件名以a字母開頭,後面是任意字符的文件都刪除掉
【個人Linux,我作主!】通配符和正則表達式深層解析
(2.11)第七個是「\」反斜線,表示轉義符,有時候咱們在當前系統中安裝vsftp軟件的時候咱們可能會使用「# yum install vsftp*」進行安裝,可是因爲咱們在執行系統命令的時候,首先是在shell進程中運行而後纔到達YUM倉庫中去進行相關的軟件包查找工做。即咱們在執行「vsftp*」的時候,shell會首先對「vsftp*」進行shell解析,查找當前目錄中是否有符合「vsftp*」格式的文件,若是如今咱們的當前目錄中存在着一個文件vsftp123,則此時shell會將「vsftp*」解析成「vsftp123」,而後再到YUM倉庫中去查找「vsftp123」的軟件包進行安裝,而這樣的狀況並非咱們所但願的。因此咱們在shell中執行安裝軟件包的命令時,通常是建議使用轉義符「# yum install vsftp\*」這樣的格式進行安裝是比較好的,這樣就能夠防止shell對咱們所使用的通配符進行解析的狀況產生。
# yum install vsftp\*---使用轉義符對通配符進行轉義,防止shell對通配符進行解析
# yum install 'vsftp*'---也可使用單引號來進行轉義,防止shell對通配符進行解析
(2.12)須要注意的是,咱們在建立文件的時候,文件名是不可能包含「/」的,由於有「/」就是表明建立了一個目錄。
# touch rh124/cc---此時「rh124/cc」並非表示一個文件名,而是表示在rh124/目錄下建立一個cc文件
【個人Linux,我作主!】通配符和正則表達式深層解析shell


(三)正則表達式的使用
(3.1)正則表達式是用來匹配字符串的,針對文件內容的文本過濾工具,大都用到正則表達式,如vim、grep、awk、sed等。正則表達式和咱們上面說的通配符實現的效果都是同樣的,是爲了實現查詢信息的模糊匹配。
(3.2)第一個「^」表示開頭,例如咱們先將/etc/passwd文件拷貝到當前目錄中,而後查詢passwd文件中以root字符開頭的行,此時可使用「^」來進行標識。
# grep ^root passwd
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.3)第二個「$」表示行末,咱們先將passwd文件中的相關行進行設計一下,而後查找每一行行末是「bash」字符的行。
# grep bash$ passwd---查詢行末字符是bash字符的全部行
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.4)第三個「\<」或者「\b」表示錨定的是單詞的開頭,咱們先來建立一個aa.txt的文件,而後咱們查詢「\<tom」以tom字符開頭的全部行。
# grep '\<tom' aa.txt---查詢以tom字符開頭的全部行
# grep '\btom' aa.txt---查詢以tom字符開頭的全部行
【個人Linux,我作主!】通配符和正則表達式深層解析vim

【個人Linux,我作主!】通配符和正則表達式深層解析
(3.5)第四個「\>」或者「\b」表示錨定的是單詞的末尾,在aa.txt文件中,咱們查詢「tom\>」以tom字符結束的全部行(圖1-17)。若是咱們但願查詢出全部以tom爲單詞獨立存在的行時,咱們能夠同時使用「\<」和「\>」符號(圖1-18)。
# grep 'tom\>' aa.txt---查詢「tom\>」以tom字符結束的全部行
# grep 'tom\b' aa.txt---查詢「tom\b」以tom字符結束的全部行
# grep '\<tom\>' aa.txt---查詢出全部以tom爲單詞獨立存在的行
# grep '\btom\b' aa.txt ---查詢出全部以tom爲單詞獨立存在的行
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.6)示例:如今咱們但願查詢SELinux中對端口設置的上下文信息,若是須要過濾具體的端口號的信息,則可使用「\<\>」來指定獨立的單詞信息,例如過濾出只包含80端口上下文的行,若是咱們只是使用「grep 80」過濾出的信息是不正確的(圖1-19),咱們應該使用「grep '\<80\>'」纔是正確的(圖1-20)。
# semanage port -l | grep 80---查詢當前系統中全部包含80端口上下文的信息
# semanage port -l | grep '\<80\>'---查詢當前系統中只含有80端口上下文的信息行
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.7)第五個「.」表示單個任意字符,和通配符中的「?」問號的意義一致。例如咱們想要匹配出aa.txt文件中to單詞後跟任意一個字符的全部符合要求的行(圖1-21)。若是咱們但願「.」符號沒有模糊查詢的意思,就表明它自己的字符的意思,則咱們可使用「\」做爲轉義符,這樣就能夠直接查詢出包含「to.」字樣的行(圖1-22)。
# grep 'to.' aa.txt---查詢出全部符合to單詞後還會跟一個任意字符的行
# grep 'to\.' aa.txt---使用轉義符,直接查詢包含「to.」字符的行
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.8)第六個「[]」,表示的是匹配指定範圍內的任意單個字符。
(3.9)第七個「[^]」,表示的是匹配指定範圍外的任意單個字符。
(3.10)分組概念
(3.10.1)第八個「\(\)」,表示的是分組。例如「\(ab\)*」表示ab單詞能夠出現0次、1次或任意次。咱們建立一個test.txt文件(圖1-22-1),而後咱們使用「\(ab\)*」將符合條件的都篩選出來(圖1-22-2)。
# grep "(ab)*" test.txt
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.10.2)咱們建立一個文件test3.txt,而後編輯以下的內容,咱們查詢「l..e」與「l..e」之間有任意字符任意次的全部符合條件的行,此時咱們發現test3.txt文件中的第1行至第4行的內容都被篩選出來了(圖1-22-4)。此時咱們若是但願出現的行中先後兩個字符是徹底一致的才符合要求並顯示,即test3.txt文件中的第1行和第3行顯示出來,此時咱們須要使用後項引用的方式來完成要求(圖1-22-5)。
分組:\(\)
後項引用:
\1:引用第一個左括號以及與之對應的右括號所包括的全部內容
\2:引用第二個左括號以及與之對應的右括號所包括的全部內容
\3:引用第三個左括號以及與之對應的右括號所包括的全部內容
# grep 'l..e.*l..e' test3.txt---查詢「l..e」與「l..e」之間有任意字符任意次的全部符合條件的行
# grep '\(l..e\).*\1' test3.txt---查詢例如「like」開頭與「like」結尾的先後對應行
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.10.3)示例:咱們在當前目錄下建立一個inittab的文件,而後咱們查詢文件中行中出現了任意一個數字,在行尾結束時也出現了這個相同的數字的行,將這個行顯示在屏幕上。
# grep '\([0-9]\).*\1$' inittab---其中「\([0-9]\)」表示行中出現的任意一個數字,「\1$」表示在行尾結束時也出現了這個相同的數字
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(3.11)咱們在使用grep命令的時候可使用「-A」、「-B」、「-C」參數,其中-A表示的是after後面,其中-B表示的是before前面,其中-C表示的是context上下文。
# grep -A 2 '^core id' /proc/cpuinfo---表示core id字符開頭行的後面的2行
# grep -B 2 '^core id' /proc/cpuinfo---表示core id字符開頭行的前面的2行
# grep -C 2 '^core id' /proc/cpuinfo---表示core id字符開頭行的上下文各2行
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析bash


(四)擴展正則表達式的使用
(4.1)以上咱們所使用的正則表達式在進行查詢的時候能夠配合grep命令進行使用「grep 表達式 file」。不過有些正則表達式grep命令並不支持,此時咱們應該使用「grep -E 表達式 file」或者「egrep 表達式 file」啓用擴展的正則表達式進行查詢。有時候還有一些正則表達式是擴展的正則表達式也解決不了的,此時咱們應該使用「grep -P 表達式 file」即調用perl語言中的正則表達式進行查詢。分割線擴展正則表達式。
注意:egrep -o表示的是僅僅輸出查詢出的字符
(4.2)第一個「?」表示它前面出現的字符,出現0次或者1次。「to.?」表示的意思是to後會跟一個任意的字符,可是這樣任意的字符可能出現0次,也可能出現1次,因此此時aa.txt 文件中包括「to」在內的全部行都是符合要求的。此時因爲使用的「?」問號,因此咱們須要使用擴展的正則表達式egrep進行匹配查詢。
# egrep 'to.?' aa.txt---其中to後會跟一個任意的字符,可是這樣任意的字符可能出現0次,也可能出現1次
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.3)第二個「+」表示它前面的字符出現1次或者屢次。此時咱們查詢「to.+」表示的意思是在to單詞後面有一個任意字符,同時這個任意字符出現多是1次,也可能出現屢次,因此在aa.txt文件中除了第一行不符合要求,其餘的行都是符合要求的。同時咱們須要使用擴展的正則表達式egrep進行匹配查詢。
# egrep 'to.+' aa.txt---也稱貪婪匹配,在to單詞後面有一個任意字符,同時這個任意字符出現多是1次,也可能出現屢次
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.4)第三個「*」表示它前面的字符出現任意次數。此時咱們查詢「to.*」表示匹配的是to單詞後有一個任意字符,而且這個任意字符出現任意次,包括0次、1次、任意次。因此此時aa.txt文件中全部行都是符合匹配的要求的。同時咱們須要使用擴展的正則表達式egrep進行匹配查詢。
# egrep 'to.*' aa.txt---查詢匹配to單詞後有一個任意字符,而且這個任意字符出現任意次,包括0次、1次、任意次
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.5)在模式匹配的過程當中咱們有兩個概念,第一個是貪婪匹配,第二個是懶惰匹配,默認是工做在貪婪模式中。其中貪婪匹配表示的是儘量多的向後面進行匹配,例如「to.+」表示的是to單詞後會有一個任意字符,而且這個任意的字符至少是1個,最多能夠任意的個數,因此匹配的時候符合要求的行會盡量的向後進行匹配,同時咱們須要使用擴展的正則表達式egrep進行匹配查詢(圖1-26)。而懶惰匹配表示的是在符合要求的狀況下儘量少的向後進行匹配,例如「to.+?」表示的是to單詞後會有一個任意字符,「+」表示而且這個任意字符至少匹配一個,最多能夠匹配任意的個數,「?」表示前面的部分能夠出現0次或者1次,因此此時就會按照最少符合要求的狀況進行懶惰匹配,同時咱們須要使用擴展的正則表達式「grep -P」進行匹配查詢(圖1-27)。以上的應用也是很是普遍的,有時候咱們在網站進行信息抓取的時候咱們但願從<p>標誌位開始的抓取,到</p>標誌位結束,此時若是咱們使用貪婪匹配的模式進行抓取,那麼咱們抓取的信息便包含a和b兩段內容,若是咱們使用懶惰匹配的模式進行抓取,那麼咱們抓取的信息就只會包含a段的內容(圖1-28)。
# egrep 'to.+' aa.txt---貪婪匹配,在to單詞後面有一個任意字符,同時這個任意字符出現多是1次,也可能出現屢次,同(3.9)
# grep -P 'to.+?' aa.txt---懶惰匹配,調用Perl語言支持的正則表達式,而後在匹配的過程當中匹配最少符合要求的字符信息
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.6)第四個是在使用grep -P時的「{n,m}」,在使用常規grep時的「{n,m}」,表示的是匹配次數在n到m之間,包括邊界;其中grep -P時的「{n}」或者常規grep時的「{n}」表示必須匹配n次;grep -P時的「{n,}」或者常規grep時的「{n,}」表示匹配n次及以上。
# grep -P 'tom{2}' aa.txt---查詢m出現兩次的全部符合字段
# grep -P 'tom{2,}' aa.txt---查詢m出現次數在兩次及兩次以上的全部符合字段
# grep 'tom{2,}' aa.txt---查詢m出現次數在兩次及兩次以上的全部符合字段,因爲使用的是常規grep,因此須要用「{2,}」表示
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.7)第五個是可使用指定的字符表示特定類型的一類字符。
[[:alpha:]]:表示全部字母
[[:alnum:]]:表示字母與數字字符
[[:ascii:]]:表示ASCII字符
[[:blank:]]:表示空格或製表符
[[:cntrl:]]:表示ASCII控制符
[[:digit:]]:表示數字
[[:graph:]]:表示可見字符,非控制、非空格字符
[[:lower:]]:表示小寫字母
[[:print:]]:表示可打印字符
[[:punct:]]:表示標點符號字符
[[:space:]]:表示空白字符,包括垂直製表符
[[:upper:]]:表示大寫字母
[[:xdigit:]]:十六進制數字
(4.8)查詢實例
(4.8.1)示例:查詢IP地址,目前在咱們的/var/log/messages文件主要保存的是系統的日誌信息,其中也會有包含IP地址的字符信息,咱們的需求是將其中全部IP地址格式的信息所有過濾出來。因爲咱們知道IP地址的格式能夠是192.168.26.101,也能夠是1.1.1.1,因此此時咱們可使用「[0-9]{1,3}」表示IP地址的一段信息,使用「{3}」表示數字和點組成的信息重複3次,最後再加上一段數字,此時咱們即可以獲得這樣一個表示IP地址格式的正則表達式:([0-9]{1,3}.){3}[0-9]{1,3}
# less /var/log/messages---查看包含系統日誌的文件
# egrep '([0-9]{1,3}.){3}[0-9]{1,3}' /var/log/messages---查詢出日誌中全部包含IP地址的全部字符信息的行
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.8.2)示例:找出/boot/grub2/grub.cfg文件中1-255之間的數字。此時咱們可使用的正則表達式爲:\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>
# egrep '\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>' /boot/grub2/grub.cfg
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.8.3)示例:粗略查詢全部符合IP地址格式要求的字符串,例如0.0.0.0至255.255.255.255這樣的格式,此時咱們能夠按照以下的方式進行查詢。
# ifconfig | egrep -o '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>'
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.8.4)示例:精確查詢全部格式爲IP地址,而且符合五類IP地址中A類、B類、C類IP地址的全部適合的字段。
A類:1-127
B類:128-191
C類:192-223
# ifconfig | egrep '\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>'
【個人Linux,我作主!】通配符和正則表達式深層解析
(4.9)通常咱們在表示正則表達式中表達式的部分的時候是建議加上單引號將表達式引發來的。若是咱們在系統中若是原先存在一個toz文件名的文件,此時咱們對錶達式不加單引號的狀況下,首先會將查詢的「to?」發送到shell中進行shell解析,此時sehll會對應「to?」在系統中查找並解析成「toz」,而後再將「toz」發送到egrep中進行解析,此時在aa.txt文件中是查詢不出來任何信息的。因此通常是須要將表示正則表達式中表達式的部分的時候是建議加上單引號這樣能夠防止shell解析的狀況發生。
# egrep 'to?' aa.txt---查詢aa.txt中to單詞後出現一個任意字符,這個任意字符出現0次或者1次
# egrep to\? aa.txt---和以上使用單引號的效果一致
【個人Linux,我作主!】通配符和正則表達式深層解析框架

—————— 本文至此結束,感謝閱讀 ——————less

相關文章
相關標籤/搜索