Linux Shell三劍客之Grep


假設有一個文件(或一堆文件),並且想要在這些文件中搜索特定的字符串或配置關鍵字。Windows下,你可能會打開這些文件用搜索框(CTRL+F)輸入關鍵字點搜索,這很麻煩而且還不能隨心所欲的搜。在Linux就不同了,我們可以用Grep,可以用正則表達式隨心所欲的搜,不僅可以搜一個文件,還可以搜一堆文件。搜索的入口和出口可以對接上管道,搜索別的工具的結構或者把搜索結果傳遞給其他工具用。

Linux Shell三劍客之Grep

今天我們就來講Linux Shell下的文本處理三劍客之Grep。為了瞭解其用法最簡便方法是使用系統幫助和man:

Linux Shell三劍客之Grep


Linux Shell三劍客之Grep

其中man的比較詳細,來自於其幫助手冊,在linux(centos為例)下查詢內置命令幫助手冊的方法是用rpm -qd grep

-q表示查詢;-d表示列出其文檔(document):

rpm -qd grep

Linux Shell三劍客之Grep

grep基礎

在開始之前,我們以centos自帶的字典文件為範例,該文件位於/usr/share/dict/words

wc /usr/share/dict/words

479829 479829 4953699 /usr/share/dict/words

文件包含48萬個單詞,一行一個單詞,由centos的word包提供。grep 也有一個-c(--count)選項對搜索匹配的行進行統計,我們先來用他來統計下它的單詞樹

grep --count '.' /usr/share/dict/words

479829

這和wc的結果一樣。

搜索中我們制定了模式為".",表示搜索包含至少一個字符,空格,空格,製表符等的行。

grep正則表達式基礎

grep最重要兩個優點:一個是搜索相當快,一個是支持正則表達式(RE,regexes)。正則表達式讓grep變得更強大。所以我們首先要介紹下正則表達式基礎。

開頭

假設我們想搜以C開頭單詞,我們需要要使用正則模式的開頭模式:(^)加一個開頭字符。比如:

Linux Shell三劍客之Grep

結尾

要搜索以特定字符結尾的模式,使用符號($)表示字符串的結尾。比如要搜索以sth結尾的單詞

grep 'sth$' /usr/share/dict/words

Linux Shell三劍客之Grep

其他RE模式

正則表達式語法很複雜,而且各個系統可能略有差異,具體需要參考對應文檔,grep中常用的語法還有:

. 表示單個字符

* 表示其之前字符出現0次或者多次,比如.*表示任意字符。

+ 表示其之前字符出現1個或者多個。注意這個只在強化的egrep或者grep -E下可用。基本grep下要用\\+

? 表示其之前字符出現0個或者一個。基本grep下要用\\?

{}表示之前字符出現的次數限定,比如:{n} n次,{n,m}n到m次,{n,}至少n次,{0,m}最多m次。grep下要用\\{n\\}

[a-z] [0-9] 表示a~z,0~9的範圍。

[^] 取反,表示匹配除了範圍之外的模式。

\\: 詞首,\\>, \\b:詞尾。

() 表示分組。基本grep下要用\\(\\)。

| 表示邏輯或,匹配多個表達式的任何一個。基本grep下要用\\|

清除註釋(-v)

前面初窺grep的門道,我們接著以一些實例來說明寫grep的具體應用。我們知道在linux下很多配置文件都包含了大量的註釋(#開頭的行),解釋很詳盡,但是一般我們不願去仔細瞭解,所以希望瀏覽時候去除掉。我們以ntp.conf為例:

cat /etc/ntp.conf

Linux Shell三劍客之Grep

grep 的-v選項表示排除模式,表示顯示所有不匹配的內容,比如要去除ntp.conf中的註釋我們使用:

grep -v '^#' /etc/ntp.conf

Linux Shell三劍客之Grep

上面所有註釋行都用空行了,顯示清晰了一點,但是看著也有點彆扭,不是嗎?

那我們就想辦法去掉空行,方法也簡單就是用管道對接到另一個grep,再去除掉空行($)

grep -v '^#' /etc/ntp.conf |grep -v '^$'

Linux Shell三劍客之Grep

OK,這下清爽多了。

僅輸出/et /passwd用戶名(-o)

為了演示grep的功能和正則表達式的用法,我們需要解析/etc/passwd文件並僅打印用戶名。

cat /etc/passwd

Linux Shell三劍客之Grep

文件中各行的字段具體含義:

<name>::::<gecos>::<shell>/<gecos>/<name>

為了僅輸出用戶名,可以使用如下查詢

grep -o '^[a-zA-Z_-]\\+' /etc/passwd

Linux Shell三劍客之Grep

在上面的grep命令中,我們使用了grep -o(--only-matching)選項,表示僅顯示匹配<pattern>的行那部分。/<pattern>

顯示臨近行(-C,-A,-B)

我們在查看日誌時候,有時不能只看匹配的行,而需要上下文信息。grep也提供了這樣的功能,顯示匹配行之前或者之後的行。這在故障排查過程中非常有用,你再也不需要打開文章,定位,然後再看上下文了。

-C n 表示打印匹配行及前後n行的信息。此處-C可以省略,用-n

-A n表示打印匹配行及之後n行的信息。

-B n表示打印匹配行及之前n行的信息。

比如我們搜索tomcat catalina.out日誌中的嚴重錯誤,可以用:

grep 'SEVERE: Error' catalina.out

Linux Shell三劍客之Grep

由於缺乏上下文,具體信息無法獲取。這時候就可以使用-C

grep -20 'SEVERE: Error' catalina.out

這樣可以獲取完成錯誤信息進行錯誤定位:

Linux Shell三劍客之Grep

搜索二進制文件(-a)

grep 是一個文本三劍客之一,但是文本劍客並不意味著他就只能處理文本文件了。實際上對二進制文件也是可以的。這就是grep的-a(--binary-files=text)選項,可以對二進制的文本進行搜索和顯示。這在安全領域很有用,比如有時候需要對某些文件判斷是否有害,是否有木馬,可以簡單用grep搜索其特徵即可。我們舉個例子比如,對一個java class文件x.class,我們用javap解析這個類文件

javap x.class

Linux Shell三劍客之Grep

我們用grep –a查看:

grep -a '.' x.class

Linux Shell三劍客之Grep

有World,我們用他做關鍵字搜索

grep -ia 'world' x.class

就能搜到結果:

ello World,..

java/lang/Objectjava/lang/SystemoutLjava/io/PrintStream;java/io/PrintStreamprintln(Ljava/lang/String;)

注意上面用了-i選項,表示忽略大小寫,也是常用的grep選項之一。

總結

本文我們介紹了Linux下的shell三劍客之一,文本搜索神器grep,希望能對大家有所幫助。其他兩個劍客是流式文本處理工具sed 和awk語言,以後有機會我們再做介紹。


分享到:


相關文章: