UpDate 2018-10-22
Author unnam3d
Tip Please feel free to contact me via mail above for any confusion or suggestions
grep, egrep, fgrep - print lines matching a pattern
grep(Global Research)亦即根據(jù)某一個模式(過濾規(guī)則)去全局性的搜索文本,并將符合模式的文本行顯示出來蜂林。grep其本身的意義是做部分匹配产艾,也就是說廊遍,當(dāng)你使用grep進(jìn)行搜索的時候璃谨,只要某一行的內(nèi)容里部分匹配蚀瘸,grep就會將結(jié)果顯示出來芽狗。而這里的模式(Pattern)是指绢掰,文本字符和正則表達(dá)式的元字符組合而成的匹配條件。簡而言之,grep就是使用基本正則表達(dá)式定義的模式來過濾文本的命令滴劲。
notice:grep 默認(rèn)工作在貪婪模式下攻晒,也就是在匹配的過程中,會盡可能長的匹配班挖,能匹配到哪就匹配到哪鲁捏。
usage: grep [options] PATTERN [FILE...]
-
option
-i, --ignore-case:忽略模式和輸入文件中的大小寫
--colour, --color:將匹配到的內(nèi)容彩色輸出
-v:反向查找,顯示沒有被模式匹配到的行
-o:只顯示被模式匹配到的字符串萧芙,每個字符串顯示為一行
-E:使用擴(kuò)展正則表達(dá)式
-A #:這其中的#表示一個數(shù)字碴萧,當(dāng)使用grep匹配到字符串后,不僅顯示匹配到的行末购,還顯示該行后面#個行的內(nèi)容破喻,可以理解為after
-B #:同-A意義相同,不同的是盟榴,顯示的是匹配到的行前面#個行的內(nèi)容曹质,可以理解為before
-C #:顯示的是匹配到的行前后#個行的內(nèi)容,可以理解為context
## option的例子
## *first* 表示 first是有顏色的
## grep -E = egrep 這里不做舉例
## fgrep可以快速搜索擎场,但不支持正則表達(dá)式氛雪,模式中的字符會被當(dāng)做字符本身去匹配。
$ cat >> test.txt << EOF
> This is the first line
> This is the second line
> This is the third line
> EOF
$ grep -iv 'First' test.txt
This is the second line
This is the third line
$ grep --color 'first' test.txt
This is the *first* line
$ grep -io 'First' test.txt
first
$ grep -A1 'second' test.txt
This is the second line
This is the third line
$ grep -B1 'second' test.txt
This is the first line
This is the second line
$ grep -C1 'second' test.txt
This is the first line
This is the second line
This is the third line
正則表達(dá)式(REGgular EXPression, REGEXP)
正則表達(dá)式分為基本正則表達(dá)式(Basic REGEXP)與擴(kuò)展正則表達(dá)式(Extended REGEXP)讥裤。
無論是哪一種趾唱,正則表達(dá)式都含義幾個特性:
- 元字符
- 位置錨定
- 分組
元字符
正則表達(dá)式里都有一些元字符,這些元字符不表示其本身的意義站欺,而是在正則表達(dá)式中有其特定的意義姨夹。我在bash特性簡單梳理一文中提及過文件名通配(globbing)。
在文件名通配中矾策,這些元字符的特定意義如下:
- '*' : 匹配任意長度的任意字符
- '?' : 匹配任意單個字符
- '[]' : 匹配指定范圍內(nèi)的任意單個字符
- '[^]' : 匹配指定范圍外的任意單個字符
而在正則表達(dá)式中磷账,元字符的特定意義為:
- '.': 表示任意單個字符
- '[]': 匹配指定范圍內(nèi)的任意單個字符
- '[^]': 匹配指定范圍外的任意單個字符
- '*': 表示匹配其前面的字符任意次
- '.*': 表示任意長度的任意字符
- '?': 表示匹配其前面的字符1次或0次
- '\{m, n\}': 表示匹配其前面的字符至少m次,至多n次
除了這些特定的元字符的意義外贾虽,正如文件通配符中所描述的字符集合逃糟,正則表達(dá)式同樣支持字符集合:
- [:space:] 表示空白字符
- [:punct:] 表示標(biāo)點(diǎn)符號
- [:lower:] 表示小寫字母
- [:upper:] 表示大寫字母
- [:alpha:] 表示大小寫字母
- [:digit:] 表示數(shù)字
- [:alnum:] 表示數(shù)字和大小寫字母
# 示例解析
$ grep 'a.b' test.txt
它只能匹配a與b之間存在一個字符的字符串,而之間存在的字符串是什么是任意的蓬豁。因此輸出結(jié)果只有 aab, acb, adb
$ grep 'a*b' test.txt
它匹配的是以b結(jié)尾绰咽,b前面具有任意個a的字符串,任意個包括零個地粪,因此它只匹配到了 b, ab, aab 而 acb adb amnbamnbamnb 也之所以顯示出來取募,是因?yàn)間rep的本身意義做的是部分匹配,只要改行有匹配到的內(nèi)容就把該行顯示出來驶忌。
$ grep 'a.*b' test.txt
它匹配的是以a開頭矛辕,b結(jié)尾笑跛,中間可以存在任意個字符,且可以是任意字符聊品。因此它就把a(bǔ)開頭b結(jié)尾的所以字符都顯示了出來飞蹂,ab, aab, acb, adb, amnbamnbamnb
$ grep 'a\?' test.txt
它匹配包含一次a或者0次a的字符串,所以只要有a翻屈,就可以被檢測出來陈哑,結(jié)果就如上了。
$ grep 'a\{1,\}b' test.txt
它匹配b前面最少有一次a的字符串伸眶,也就是ab, aab, aaab等等惊窖,所以結(jié)果如上。
$ grep 'a\{0,3\}' test.txt
它匹配包含最多三個a厘贼,所以結(jié)果如上界酒。
位置錨定
位置錨定,就是在進(jìn)行搜索的時候嘴秸,所搜索的字符必須出現(xiàn)在特定的位置毁欣。
'^': 錨定行首,此字符后面的任意字符串內(nèi)容必須出現(xiàn)在行首岳掐。
'$': 錨定行尾凭疮,此字符前面的任意字符串內(nèi)容必須出現(xiàn)在行尾。
'^$': 錨定空白行串述,也就是搜索文件中的空白行执解。
'\<'或'\b': 錨定單詞首部,此字符后面的任意字符串必須出現(xiàn)在單詞首部纲酗。
-
'\>'或'\b': 錨定單詞尾部衰腌,此字符后面的任意字符串必須出現(xiàn)在單詞尾部。
notice: 這里單詞的含義并不特指英文的單詞耕姊,它只要以一個字符開始桶唐,以一個字符結(jié)束,中間只要沒有出現(xiàn)特殊字符茉兰,它這個字符串整體就叫做單詞,而這特殊字符包括:
. :
# 示例解析
$ grep '^r..t' test.txt
它將匹配到r..t的字符串欣簇,并且還是位于行首的行顯示出來规脸。
$ grep 'r..t$' test.txt
它將匹配到r..t的字符串,并且還是位于行尾的行顯示出來熊咽。
$ grep '^$' test.txt
它將空白行顯示出來
$ grep 'fork\>' test.txt
它將匹配到的字符fork莫鸭,并且還是位于單詞尾部的行顯示了出來。
$ grep '\<ar' test.txt
它將匹配到的字符ar, 并且還是位于單詞首部的行顯示了出來横殴。
$ grep '\<useful\>' test.txt
它將匹配到的字符useful, 并且是整個單詞的行顯示了出來被因。
分組
分組的意義卿拴,通俗的來講,就是將一捆字符作為一個整體來看待梨与,用\(\)
來表示堕花。
例如:\(ab\)*
將ab作為一個整體,星號修飾的ab這一個整體粥鞋。而ab*僅僅修飾b一個字符
$ grep '\(ab\)*' test.txt
上面這個命令就表示在文件test.txt
中匹配ab這一整體缘挽,它可以匹配到ab, abab, ababab這樣。
后向引用
與分組搭配使用的還有后向引用呻粹。
\1: 引用第一個左括號以及與之對應(yīng)的右括號所包括的所有內(nèi)容
$ grep '\([0-9]\).*\1$' /etc/inittab
\2: 引用第二個左括號以及與之對應(yīng)的右括號所包括的所有內(nèi)容
\3: 引用第三個左括號以及與之對應(yīng)的右括號所包括的所有內(nèi)容
<練習(xí)>
以單個空格加單個數(shù)字結(jié)尾的行
$ grep '[[:space:]][[:digit:]]$' /etc/inittab
擴(kuò)展正則表達(dá)式
擴(kuò)展正則表達(dá)式與正則表達(dá)式在很多地方的意義都是相同的壕曼。例如:
-
字符匹配:
. [] [^]
次數(shù)匹配:
* ? {m,n}
位置錨定;
分組等浊;
NOTICE:
- 次數(shù)匹配中的
?和{m,n}
不需要加反斜線 \ - 分組也不需要加反斜線腮郊,而且這里的分組才真正意義上實(shí)現(xiàn)了分組的意義。也支持
\1, \2, \3
的引用筹燕。
除了與正則表達(dá)式相同意義的地方轧飞,擴(kuò)展表達(dá)式也有其獨(dú)特的地方:
次數(shù)匹配中
+
加號代表基本正則表達(dá)式中的\{1,\}
,所以加號代表匹配其前面的字符至少一次-
支持邏輯或:a|b = a 或 b
C|cat: C或cat
$ grep --color -E 'C|cat' test.txt
(C|c)at: Cat或cat
$ grep --color -E '(C|c)at' test6.txt
-
grep -E = egrep
egrep --color '\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>' /boot/grub/grub.conf
練習(xí)
- 找出ifconfig命令中0-255之間的數(shù)字
- 找出ifconfig命令中形如x.x.x.x格式的數(shù)字格式
- 找出ifconfig命令中的ip地址
答案
ifconfig | egrep --color '\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>'
ifconfig | egrep --color '(\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>'
ifconfig | egrep --color '(\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\>\.){3}\1'
ifconfig | egrep --color '\<[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]{2}|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-4])\>'