歡迎光臨
每天分享高質量文章

Linux下的文本查找技巧,你掌握了嗎?

作者:守望,Linux應用開發者,目前在公眾號【編程珠璣】 分享Linux/C/C++/資料結構與演算法/工具等原創技術文章和學習資源。

前言

之前介紹過很多linux下查找相關的命令,例如《Linux中的檔案查找技巧》,《find命令高級用法》,《如何查看linux中檔案打開情況》等等,而對檔案內容搜索的命令似乎還沒有涉及,因此本文介紹文本搜索命令–grep。

常見用法

我們會經常結合管道符(|)來使用它,即在前面命令執行的結果中查找包含相關字串的內容。例如:

$ ps -ef|grep redis

ps -ef用於查看系統行程情況,但是它列出的結果很多,如果我們只想看到自己需要的,則通過管道符,用grep進行過濾搜索,例如搜索redis相關的行程,最後它只會列出和redis相關的行程了:

$  ps -ef|grep redis
root     10748 10733  0 21:14 pts/21   00:00:00 redis-server *:6379
root     10754 10733  0 21:14 pts/21   00:00:00 grep --color=auto redis

那麼如果要排除某些不相關信息呢?我們可以使用-v引數

$ ps -ef|grep redis |grep -v auto
root     10748 10733  0 21:14 pts/21   00:00:00 redis-server *:6379

這樣一來,包含auto相關的結果就不會出現在最終結果里了。

如果只想統計結果數量呢?我們可以結合-c(count)引數:

$ ps -ef|grep redis -c
2

檔案內容搜索

好了,說完了最常見的用法,我們來看看如何搜索檔案內容。實際上awk和sed在這方面也頗有經驗,不過本文的主角是grep,所以另外兩個命令暫時不涉及。我們來看幾個實體。

在指定檔案中查找指定關鍵字

例如,要在linux_command_debug.md檔案中,查找test字串:

$  grep "test" aaa/bbb/linux_command_debug.md
int test(int a,int b)
    test(a,b);

如果想要顯示指定關鍵字的行號,可以使用-n引數,例如:

$  grep -n "test" aaa/bbb/linux_command_debug.md
18:int test(int a,int b)
27:    test(a,b);

搜索時指定或排除多個檔案

前面提到了對一個檔案內容進行搜索,如果是多個呢?或者不想從某些檔案里搜索呢?

如果想對檔案進行指定也是可以的,例如搜索所有的md結尾的檔案:

$  grep -n "test" *.md

或者可以使用–exclude引數來排除某些檔案,例如,查找包含test,但是排除txt檔案:

$ grep -rn "test" --exclude=*.txt

搜索時就會忽略.txt結尾的檔案了。

如果要排除的條件比較多,可以將要排除的條件儲存在另外一個檔案里:

$ grep -rn "test" --exclude-from=skip.txt

skip.txt的內容可以是樣式匹配的檔案名或者具體檔案名:

*.txt
test.md

這樣,以.txt結尾,以及test.md檔案都不會搜索了。

除此之外,還可以排除指定目錄,它需要用到–exclude-dir引數:

$ grep -rn "test" --exclude-dir=aaa

它在搜索時將會跳過aaa目錄下的檔案。

查找包含指定關鍵字的檔案

如果要在當前目錄下所有檔案查找包含“int main(void)”字串的檔案:

$ grep -rn "int main(void)"
aaa/bbb/c_main_func.md:49:int main(void)
aaa/bbb/c_main_func.md:71:int main(void) { /* ... */ }
aaa/bbb/c_array.md:104:int main(void)
aaa/bbb/c_array.md:129:int main(void)
aaa/bbb/pc-lint.md:42:int main(void)
aaa/bbb/pc-lint.md:128:int main(void)

這可能是最實用的使用方法之一了。這裡-r引數表示遞迴查找當前目錄的檔案,-n會顯示查找位置的行號,如果只想顯示包含該指定關鍵字的檔案名,可使用-l(–file-with-matches)引數:

$ grep -rln "int main(void)"
aaa/bbb/c_main_func.md
aaa/bbb/c_array.md
aaa/bbb/pc-lint.md

如果你嘗試一下就會發現,如果不帶-r引數,它會暫停,等待你從控制台輸入,例如:

$ grep -n "test"
test
1:test

所以使用時記得帶上相關引數奧!

查找不包含指定關鍵字的檔案

前面提到瞭如何查找包含某個關鍵字的檔案,如果要找的是不包含該關鍵字的檔案呢?
實際上只要使用-L引數即可:

$ grep -rLn "int main(void)"
(這裡會顯示不包含指定關鍵字內容的檔案名)

搜索時忽略大小寫

使用-i(–ignore-case)引數即可:

$ grep -rni "int MAIN(void)"
aaa/bbb/c_main_func.md:49:int main(void)
aaa/bbb/c_main_func.md:71:int main(void) { /* ... */ }
aaa/bbb/c_array.md:104:int main(void)
aaa/bbb/c_array.md:129:int main(void)
aaa/bbb/pc-lint.md:42:int main(void)
aaa/bbb/pc-lint.md:128:int main(void)

搜索顯示不包含指定關鍵字的行

前面的大部分例子都是顯示符合條件的行,如果要顯示不符合條件的行呢?可以用我們前面提到的-v引數:

$ grep -rnv "int main(void)"
(內容較多,未顯示)

從結果中就會發現,它會展示出包含指定關鍵字的檔案,但是展示的是不包含該關鍵字的行。

顯示指定關鍵字前後內容

假如你需要查看包含指定關鍵字行附近的行,前面的方式是沒有辦法看到的,不過我們可以用-A(–after-context=)和-B(–before-context=)引數來顯示前後的行:

$ grep -rn "int main(void)" -A 1 -B 1
aaa/bbb/c_array.md-103-}
aaa/bbb/c_array.md:104:int main(void)
aaa/bbb/c_array.md-105-{
(其他內容省略)

通過最後加上-A和-B引數,顯示了指定關鍵字前後的行,這在日誌搜索分析時非常有用。

指定規則檔案進行搜索

如果有多個搜索關鍵字怎麼處理呢?我們可以把關鍵字寫在一個檔案,搜索時指定檔案即可,例如規則檔案為key.txt:

int main(void)
test

從指定檔案中搜索上面的關鍵字:

$ cat filename |grep -f key.txt

這樣結果就會顯示匹配key.txt檔案中所有關鍵字的行,非常適合用於多個條件的搜索。

正則運算式搜索

看完前面的內容,是不是還沒有感受到grep的強大?grep的另一個強大之處是,它的搜索支持正則運算式,例如查找文本行以t開頭,以t結尾的檔案:

$ grep -rn ^t.*t$
key.txt:2:test
aaa/bbb/c_operate_redis_start.md:68:typedef struct Stu_Info_Struct
aaa/bbb/c_operate_redis_start.md:101:typedef struct Stu_Info_Struct

其中^t,表明以t開頭,t$表明以t結尾,如果需要使用擴展的正則運算式進行搜索,可使用egrep命令。關於正則運算式的寫法,本文不做詳細介紹。

總結

在內容搜索方面,grep常常能夠助我們一臂之力,因此掌握grep的使用也是linux學習不可缺少的一部分,當然我們不需要完全記住每個引數的作用,但我們至少知道有這樣的引數,並且在需要時能夠快速查詢到。本文常用引數如下:

  • -v #顯示不包含匹配關鍵字的所有行。

  • -l #顯示包含匹配關鍵字的檔案

  • -L #顯示不包含匹配關鍵字的檔案

  • -r #遞迴搜索

  • -i #忽略大小寫

  • -n #顯示關鍵字所在行號

  • -A n #顯示關鍵字後n行

  • -B n #顯示關鍵字前n行

  • –exclude #搜索時排除某些檔案

  • –exclude-dir #搜索時排除某些目錄

  • -f #指定規則檔案進行搜索

已同步到看一看
赞(0)

分享創造快樂